Winsock многопоточный сервер не работает хорошо, когда несколько клиентов подключаются?
У меня есть сервер, который создает поток для каждого клиента, который подключается к нему. Затем поток занимается получением / отправкой данных клиенту. Вот мой код сервера:
//////////////
// START //
/////////////
while( 1 )
{
if( listen(serverSocket, SOMAXCONN) == SOCKET_ERROR )
{
printf( "Listen failed with error: %ld\n", WSAGetLastError() );
break;
}
/*
* wait for clients...
*/
clientSocket = accept(serverSocket,
(struct sockaddr *)&clientSockAddr,
&clientSockAddrLen);
if( clientSocket == INVALID_SOCKET )
{
printf("%d:accept failed\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("Client accepted: IP: %s PORT: %d\n",
inet_ntoa(clientSockAddr.sin_addr),
clientSockAddr.sin_port );
THREADDATA threadData = { clientSocket };
sprintf_s(threadData.ip, "%s", inet_ntoa(clientSockAddr.sin_addr));
// spawn a thread for each client
hthread = CreateThread(
NULL, // don't inherit handle
0, // use default size for the executable
processClient,
(pTHREADDATA)&threadData, // thread data
0, // run right away
&threadId );
}
И вот как выглядит моя функция потока:
/*
called by thread for each client
*/
DWORD WINAPI processClient(LPVOID lpParam)
{
int numBytesRecvd = 0,
numBytesSent = 0,
index = 0,
nLeft = SIZE,
TOTAL = SIZE;
char buff[SIZE];
int run = 1;
char msg[MSG_SIZE];
pTHREADDATA td = (pTHREADDATA)lpParam;
/* keep processing client */
while (run)
{
memset(buff, 0, SIZE);
numBytesRecvd = recv(td->clientSocket, buff, nLeft, 0);
/* CLIENT EXITED */
if( !strcmp(buff, "exit") )
{
printf("Client exited!\n");
run = 0;
}
if( numBytesRecvd > 0 )
{
printf("< %s\n", buff);
}
if (numBytesRecvd == 0)
{
printf("Client closed!\n");
run = 0;
}
if( numBytesRecvd == SOCKET_ERROR )
{
printf("%d:Recieve error!\n", WSAGetLastError());
run = 0;
}
}
closesocket(td->clientSocket);
ExitThread(0);
return 0;
}
Выпуск:
Итак, я запускаю сервер и клиент, скажем client1 (из командной строки в win 7), все в порядке. Когда я что-то печатаю на терминале client1, это печатается на терминале сервера.
Теперь я запускаю другой клиент, client2, он подключается к серверу, и все, что я печатаю, отображается на сервере, но теперь, когда я что-то печатаю на client1, оно не отображается на терминале сервера.
Таким образом, в основном каждый раз, когда я запускаю новый клиент, только тот клиент может общаться с сервером, старые клиенты не могут!!! Но я думал, что поток будет продолжать обрабатывать каждого клиента? Или это, что приглашение cmd в Windows не является потокобезопасным?
1 ответ
Здесь я вижу две вероятные проблемы: 1) Вы передаете threadData в стеке другому потоку. Вы должны разместить его в куче, а затем передать его потоку. 2) Я думаю, что вы не назначаете clientSocket правильно для threadData, разве вы не должны назначать член структуры threadData?