【问题标题】:TCP Winsock: accept multiple connections/clientsTCP Winsock:接受多个连接/客户端
【发布时间】:2013-02-17 14:04:06
【问题描述】:

我试图增加客户端,并将其发送给每个客户端。 但它只适用于一个,在一个客户端连接服务器后,它对传入的连接毫无用处。

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;

    }
}

【问题讨论】:

    标签: c++ sockets winapi tcp winsock2


    【解决方案1】:

    当然不能接受新客户端,因为服务器只处理接受的客户端,即服务器正忙。

    解决方案很简单:为每个接受的客户端创建一个新线程并在那里处理客户端会话。只需使用_beginthreadex() (#include &lt;process.h&gt;):

    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() 函数不保证所有数据会在一次调用中发送/接收。有关这些函数的返回值,请参阅文档。

    【讨论】:

      【解决方案2】:

      接受套接字后,为客户端请求创建单独的线程。然后继续等待新的接受。

      例如:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-24
        • 1970-01-01
        • 2015-04-20
        • 2010-11-18
        • 2014-04-07
        • 2012-11-16
        相关资源
        最近更新 更多