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 ответ

Все ваши клиентские потоки получают указатель на один и тот же 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);      
}
Другие вопросы по тегам