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);
}