2013-03-03 101 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

你這麼多!!!!!!!工作完美! – 2013-03-03 13:27:14

+0

是的,很抱歉..; D – 2013-03-04 12:04:59

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