【问题标题】:How to select and send data to a specific winsock client如何选择数据并将数据发送到特定的 Winsock 客户端
【发布时间】:2013-05-15 02:59:42
【问题描述】:

我使用 C++ 和 Winsock2 来创建服务器和客户端应用程序。它目前通过创建单独的线程来处理多个客户端连接。

两个客户端连接到服务器。两者都连接后,我只需要向连接的第一个客户端发送一条消息,然后等到收到响应后,再向第二个客户端发送一条单独的消息。 问题是,我不知道如何定位第一个连接的客户端。 我目前的代码接受两个连接,但消息被发送到客户端 2。

有人可以给我一些关于如何使用 Send() 到 特定 客户端的想法吗?谢谢

接受连接并启动新线程的代码

        SOCKET TempSock = SOCKET_ERROR;                 // create a socket called Tempsock and assign it the value of SOCKET_ERROR
        while (TempSock == SOCKET_ERROR && numCC !=2)   // Until a client has connected, wait for client connections
        {
            cout << "Waiting for clients to connect...\n\n";

            while ((ClientSocket = accept(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*)ClientSocket, 0, &threadID);
            }
        }

ClientSession()

    unsigned __stdcall ClientSession(void *data)
    {
        SOCKET ClientSocket = (SOCKET)data;

        numCC ++; // increment the number of connected clients

        cout << "Clients Connected: " << numCC << endl << endl; // output number of clients currently connected to the server

        if (numCC <2) 
            {
                cout << "Waiting for additional clients to connect...\n\n";
            }   

        if (numCC ==2)
        {
        SendRender();       // ONLY TO CLIENT 1???????????


            // wait for client render to complete and receive Done message back
            memset(bufferReply, 0, 999);                                // set the memory of the buffer
            int inDataLength = recv(ClientSocket,bufferReply,1000,0);   // receive data from the server and store in the buffer
            response = bufferReply;                                     // assign contents of buffer to string var 'message'

            cout << response << ". " << "Client 1 Render Cycle complete.\n\n";

            SendRender(); // ONLY TO CLIENT 2????????????
        }
        return 0;
    }

Sendrender() 函数(向客户端发送渲染命令)

    int SendRender()
    {
        // Create message to send to client which will initialise rendering
            char *szMessage = "Render";

            // Send the Render message to the first client
            iSendResult = send(ClientSocket, szMessage, strlen(szMessage), 0);      // HOW TO SEND ONLY TO CLIENT 1???
            if (iSendResult == SOCKET_ERROR) 
        {
                // Display error if unable to send message
                cout << "Failed to send message to Client " << numCC << ": ", WSAGetLastError();
                closesocket(Socket);
                WSACleanup();
                return 1;
        }
            // notify user that Render command has been sent
            cout << "Render command sent to Client " << numCC << endl << endl;

            return 0;
    }

【问题讨论】:

  • SendRender() 是您的职能之一吗?您应该显示相关的代码。我觉得这可能是一些全局变量问题。您的代码还有其他一些逻辑问题:您的线程中根本没有“等待”。
  • 这不只是使用适当的文件描述符作为第一个参数调用 send() 的问题吗?即,您的两个连接中的每一个都将由其自己的单独文件描述符表示,因此只需在所需的一个而不是另一个上调用 send() 即可。
  • 感谢你们两位的 cmets。我已经添加了 SendRender() 代码,对此感到抱歉。 -Nbr442 关于“等待”,恐怕我对 Winsock 很陌生并且使用多个线程,所以我不确定如何/为什么在这里实现等待。 -Jeremy 我查看了 send() 函数,但虽然我可以看到第一个参数是相关的,但我不太确定如何根据 ClientSocket 当前使用的方式来实现它。我从其他地方引入了多线程代码以适应我的目的,只是稍微修改了一下,但仍然掌握了那部分。

标签: c++ winsock2


【解决方案1】:

您可以通过添加WaitForSingleObject(或WaitForMultipleObjects)调用为线程提供等待函数和控制函数。这些 API 调用会暂停线程,直到某个其他线程设置了事件句柄。 API 返回值告诉您设置了哪个事件句柄,您可以使用它来确定要执行的操作。

为每个线程使用不同的事件句柄。要将其传递给线程,您将需要一个包含事件句柄和您现在传递的套接字句柄的结构。将指向该结构的指针传递给线程实际上是传递两个参数的一种方式。

您的主线程将需要使用 CreateEvent 来初始化线程句柄。然后在连接两个套接字后,它将设置一个事件(SetEvent),触发第一个线程。

【讨论】:

  • 感谢您对此 Scott 的回复,我将努力实施此方法
猜你喜欢
  • 1970-01-01
  • 2013-02-27
  • 2021-10-28
  • 2015-09-23
  • 1970-01-01
  • 2013-01-25
  • 2014-01-16
  • 1970-01-01
  • 2014-12-31
相关资源
最近更新 更多