Winsock API-在两个线程中同时发送和接收数据

时间:2018-07-16 10:00:23

标签: c++ winsock send

我正在尝试在同一程序中构建客户端和服务器。例如,用户1将数据包发送给用户2,用户2在收到数据包后将另一个数据包发回给用户1。问题是,运行该程序后,两个用户都没有收到该数据包。与服务器正常工作的程序分开

#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
#include <thread>

static const int num_threads = 2;

static char buffer[8096 + 1];
char a[256] = {};
char MOTD[256];

void call_from_thread(int tid) {
//  ---------- Server code: ---------- //
if( tid == 0 ){

WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0){MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);}

    SOCKADDR_IN addr;
    int addrlen = sizeof(addr);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(1112);
    addr.sin_family = AF_INET;

    SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
    listen(sListen, SOMAXCONN);

    SOCKET newConnection;
    newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
    if (newConnection == 0){
        std::cout << "Failed to accept the client's connection." << std::endl;
    }else{
        std::cout << "Client Connected!" << std::endl;
    }

    while (true){
        std::cin >> a;
        send(newConnection, a, sizeof(a), NULL);
    }
}else if( tid == 1 ){


//  ---------- Client code: ---------- //
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0){MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);}

    SOCKADDR_IN addr;
    int sizeofaddr = sizeof(addr);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(1111);
    addr.sin_family = AF_INET;

    SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket
    if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
    {
        MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
        //return 0; //Failed to Connect
    }

    std::cout << "Connected!" << std::endl;

    char MOTD[256];
    while (true){
        recv(Connection, MOTD, sizeof(MOTD), NULL); //Receive Message of the Day buffer into MOTD array
        std::cout << "MOTD:" << MOTD << std::endl;
    }
}



//  ---------- Thread selection: ---------- //
int main() {
std::thread t[num_threads];

for (int i = 0; i < num_threads; ++i) {
    t[i] = std::thread(call_from_thread, i);
 }

 for (int i = 0; i < num_threads; ++i) {
     t[i].join();
 }

}

1 个答案:

答案 0 :(得分:1)

服务器正在侦听端口1112,但是客户端正在连接端口1111。这意味着客户端和服务器之间可能根本无法相互连接,无论它们是否在同一应用程序中。

我还看到了您的代码的许多其他问题,包括:

  • WSAStartup()应该在应用启动时被调用一次,而不是每个线程被调用。

  • 如果任何WinSock函数失败,则两个线程都不能干净退出。

  • 在客户端可以连接到它之前,客户端线程不等待服务器线程打开其侦听端口。

  • 潜在的缓冲区溢出。

  • 资源泄漏。

  • 缺乏体面的错误处理。

    • 在服务器端,您完全忽略了socket()bind()listen()send()报告的错误,并且您没有检查{的返回值{1}}正确。
    • 在客户端,您完全忽略了accept()socket()报告的错误。而且,在将recv()缓冲区打印到MOTD之前,不能确保其为空终止。

尝试更多类似的方法:

std::cout