2013-03-03 4 views
2

Я попытался размножить клиентов и отправить их каждому. Но он работает только один, после того, как один клиент подключил сервер, просто бесполезный для входящих подключений.TCP Winsock: принимать несколько соединений/клиентов

while(true) 
{ 
    if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen)) 
    { 
     for(int i = 0; i < MaxUsers; i++) 
     { 
      if(!ClientAddress[i].sin_family) 
      { 
       ClientAddress[i] = IncomingAddress; 
       char Version[128], Dir[256], Path[256], URL[128], Message[256]; 
       GetCurrentDirectory(256, Dir); 
       sprintf(Path, "%s\\Version.ini", Dir); 
       GetPrivateProfileString("Default", "Version", "1.0.0.0", Version, 128, Path); 
       GetPrivateProfileString("Default", "URL", "", URL, 128, Path); 
       GetPrivateProfileString("Default", "Message", "", Message, 256, Path); 
       send(Sub, Version, 128, 0); 
       send(Sub, Message, 256, 0); 
       break; 
      } 
     } 
     continue; 

    } 
} 

ответ

11

Конечно, новые клиенты не могут быть приняты, так как сервер обрабатывает только принятый клиент, то есть сервер занят.

Решение прост: создайте новый поток для каждого принятого клиента и обработайте сеанс клиента там. Просто используйте _beginthreadex() (#include <process.h>):

unsigned __stdcall ClientSession(void *data) 
{ 
    SOCKET client_socket = (SOCKET)data; 
    // Process the client. 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ... 

    SOCKET client_socket; 
    while ((client_socket = accept(server_socket, NULL, NULL))) { 
     // Create a new thread for the accepted client (also pass the accepted client socket). 
     unsigned threadID; 
     HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)client_socket, 0, &threadID); 
    } 
} 

Кстати, send()/recv() функции не гарантируют, чтовсе данные будут посланные/полученные на один вызов. См. Документацию для возвращаемого значения этих функций.

+0

Ты так много !!!!!!! Работа прекрасна! –

+0

Да, извините ..; D –

3

После принятия гнезда создайте отдельный поток для запросов клиентов. Затем продолжайте ждать нового приема.

Например:

... 
    while (1) 
    { 
     AcceptSocket = SOCKET_ERROR; 

     while (AcceptSocket == SOCKET_ERROR) 
     { 
      AcceptSocket = accept(m_socket, NULL, NULL); 
     } 

     printf("Client Connected.\n"); 

     DWORD dwThreadId; 
     CreateThread (NULL, 0, ProcessClient, (LPVOID) AcceptSocket, 0, &dwThreadId); 
    } 
    ... 

Где функция ProcessClient может выглядеть так:

DWORD WINAPI ProcessClient (LPVOID lpParameter) 
{ 
    SOCKET AcceptSocket = (SOCKET) lpParameter; 

    // Send and receive data. 
    int bytesSent; 
    int bytesRecv = SOCKET_ERROR; 
    char sendbuf[2000]=""; 
    char recvbuf[2000]=""; 

    char timebuf[128]; 

    sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", ipaddr, port); 
    bytesSent = send(AcceptSocket, sendbuf, strlen(sendbuf), 0); 

    if (bytesSent == SOCKET_ERROR) 
    { 
     printf("Error at send hello: %ld\n", WSAGetLastError()); 
     goto fin; 
    } 

    while (1) 
    { 
     _strtime(timebuf); 
     ZeroMemory (recvbuf, sizeof(recvbuf)); 

     bytesRecv = recv(AcceptSocket, recvbuf, 32, 0); 
     printf("%s Client said: %s\n", timebuf, recvbuf); 

     if (strcmp(recvbuf, "1") == 0) 
     { 
      sprintf(sendbuf, "You typed ONE\n"); 
      //printf("Sent '%s'\n", sendbuf); 
      bytesSent = send(AcceptSocket, sendbuf, strlen(sendbuf), 0); 

      if (bytesSent == SOCKET_ERROR) 
      { 
       printf("Error at send: %ld\n", WSAGetLastError()); 
       goto fin; 
      } 
     } 
     else if (strcmp(recvbuf, "2") == 0) 
     { 
      sprintf(sendbuf, "You typed TWO\n"); 
      //printf("Sent '%s'\n", sendbuf); 
      bytesSent = send(AcceptSocket, sendbuf, strlen(sendbuf), 0); 

      if (bytesSent == SOCKET_ERROR) 
      { 
       printf("Error at send: %ld\n", WSAGetLastError()); 
       goto fin; 
      } 
     } 
     else if (strcmp(recvbuf, "exit") == 0) 
     { 
      printf("Client has logged out\n", WSAGetLastError()); 
      goto fin; 
     } 
     else 
     { 
      sprintf(sendbuf, "unknown command\n"); 
      //printf("Sent '%s'\n", sendbuf); 
      bytesSent = send(AcceptSocket, sendbuf, strlen(sendbuf), 0); 

      if (bytesSent == SOCKET_ERROR) 
      { 
       printf("Error at send: %ld\n", WSAGetLastError()); 
       goto fin; 
      } 
     } 
    } 

fin: 
    printf("Client processed\n"); 

    closesocket(AcceptSocket); 
    return 0; 
} 
Смежные вопросы