C++ 中的 Winsock 服务器在三个客户端后拒绝连接

Winsock Server in C++ Refusing Connections After Three Clients

我正在用 C++ 编写一个 Winsock 服务器,它从模数转换器收集数据并运行一个服务器,以便客户端可以登录并请求数据。我目前拥有 运行 至少三个线程(主线程、模拟输入线程和一个服务器线程),加上服务器为每个连接的客户端分拆出一个新线程。我现在正在测试代码,它三次接受来自客户端的连接,但在第四次尝试时拒绝连接。这是我用来为每个客户端接收连接和分离线程的 while 循环。当服务器拒绝连接时,它仍然在这个循环中。我从一些调试 printf 语句中知道。

while (serverActive) {
        //Accept client sockets as long as the server remains active
        ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ListenSocket == INVALID_SOCKET) {
            printf("Accept failed");
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
        std::thread clientThr(clientHandlerThread, ClientSocket);
        clientThr.detach();
    }

这是客户端处理程序线程的代码。中间的所有 if-elseif-else 语句只是我为与客户端通信而设置的协议。我正在使用的测试器客户端代码从客户端关闭套接字。我读了一些其他帖子,其中说这有时是问题所在,但在这种情况下似乎不是问题所在。有什么想法吗?

int clientHandlerThread(SOCKET client) {
    int iResult, iSendResult;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;

    char  * p_m6 = reinterpret_cast< char  *>(&data_ai_SC1Mod6[0]);
    char  * p_m7 = reinterpret_cast< char  *>(&data_ai_SC1Mod7[0]);
    char  * p_m8 = reinterpret_cast< char  *>(&data_ai_SC1Mod8[0]);

    //Receive data until the client closes the connection
    do {
        iResult = recv(client, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            recvbuf[iResult] = (char)0;
            printf("Received Command: ");
            printf(recvbuf);
            printf("\n");

            if (recvbuf[4] == 'V') {
                if (recvbuf[6] == '6') {
                    iSendResult = send(client, "SCXI>", 5, 0);
                    iSendResult = send(client, p_m6, 64, 0);
                    iSendResult = send(client, "<SCXI", 5, 0);
                }
                else if (recvbuf[6] == '7') {
                    iSendResult = send(client, "SCXI>", 5, 0);
                    iSendResult = send(client, p_m7, 64, 0);
                    iSendResult = send(client, "<SCXI", 5, 0);
                }
                else if (recvbuf[6] == '8') {
                    iSendResult = send(client, "SCXI>", 5, 0);
                    iSendResult = send(client, p_m8, 64, 0);
                    iSendResult = send(client, "<SCXI", 5, 0);
                }
                else {
                    iSendResult = send(client, "SCXI>Unrecognized Module<SCXI", 29, 0);
                }
            }
            else {
                iSendResult = send(client, "SCXI>Unrecognized Command<SCXI", 30, 0);
            }
            if (iSendResult == SOCKET_ERROR) {
                printf("Send failed");
                closesocket(client);
                WSACleanup();
                return 1;
            }
        }
        else {
            closesocket(client);
            WSACleanup();
            return 1;
        }
    } while (iResult > 0);

    closesocket(client);
    WSACleanup();
    return 0;
}

它在第一个连接线程退出后开始拒绝连接,因为您在线程中错误地调用了 WSACleanup()。去掉它。您还应该将其从接受循环中删除。你应该只在你准备好退出整个过程时调用它。

请注意,您在接受循环中测试了错误的套接字。

注意 2 您的代码做出了站不住脚的假设,即每个 recv() 都会收到一条完整的消息。