Winsock recv()阻止客户端应用程序

时间:2018-07-07 18:34:03

标签: c++ sockets winsock recv

我正在尝试创建简单的C ++服务器-客户端应用程序,该应用程序允许多个用户连接到服务器。问题在于,在为每个客户端创建新线程之后,recv函数开始使客户端应用崩溃。

这是我的代码,用于为每个连接的客户端创建新线程:

while (ClientSocket = accept(ListenSocket, 0, 0)) {
        if (ClientSocket == INVALID_SOCKET) {
            printf("\ninvalid client socket", GetLastError());
            continue;
        }
        unsigned threadID;
        HANDLE myhandleB = (HANDLE) _beginthreadex(NULL, 0, &Server::receiveMessageThread, (void *) &ClientSocket, 0,
                                                   &threadID);
    }

这是一种尝试从服务器接收消息的方法:

void waitForMessage() {
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
    }

    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( iResult > 0 );
}

致电后:

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

客户端应用停止响应。

1 个答案:

答案 0 :(得分:1)

您所有的客户端线程都接收到指向 same SOCKET变量的指针,因此它们将相互踩踏。您需要将SOCKET副本传递给每个线程。

如果成功,您还将泄漏HANDLE返回的_beginthreadex(),如果失败则泄漏被接受的SOCKET

尝试以下方法:

// make sure this is declared as 'static' in the 'Server' class declaration...
unsigned __stdcall Server::receiveMessageThread(void *arg)
{
    SOCKET ClientSocket = (SOCKET) arg;
    ...
    closesocket(ClientSocket);
    return 0;
}

...

while (true)
{
    ClientSocket = accept(ListenSocket, 0, 0);
    if (ClientSocket == INVALID_SOCKET)
    {
        printf("\ninvalid client socket", GetLastError());
        continue;
    }
    unsigned threadID;
    HANDLE myhandleB = (HANDLE) _beginthreadex(NULL, 0, &Server::receiveMessageThread, (void *) ClientSocket, 0, &threadID);
    if (myhandleB)
        CloseHandle(myhandleB);
    else
        closesocket(ClientSocket);      
}