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()
都会收到一条完整的消息。
我正在用 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()
都会收到一条完整的消息。