问题描述
for(char Index = 0; Index < MAX_CLIENTS; ++Index)
{
if(ClientSockets[Index] == INVALID_SOCKET)
{
accept(ClientSockets[Index],(sockaddr *)&Address,&AddressSize);
unsigned long iMode = 1;
if(ioctlsocket(ClientSockets[Index],FIONBIO,&iMode) != NO_ERROR)
{
Error("Making client socket unblocking has Failed.\n");
}
}
}
在主线程中,我从客户端接收数据包。
在我执行 Sleep() 后的主线程中,程序返回 1 并结束。
我发现唯一可行的方法是从接受客户端的线程中删除 ioctlsocket。
解决方法
您错误地使用了 accept()
。
accept()
的第一个参数是一个仅限输入的参数,用于指定接受待处理的客户端连接的侦听套接字。该参数不是输出参数,就像您试图将其视为一样。
您将 ClientSockets[Index]
传递给第一个参数 accept()
。但是 ClientSockets[Index]
设置为 INVALID_SOCKET
。这将使 accept()
失败,但您忽略了该错误。您需要传入您之前使用 socket()
创建的侦听套接字。
您没有将 accept()
的返回值分配给 ClientSockets[Index]
,因此它仍然设置为 INVALID_SOCKET
。然后,您将其传递给 ioctlsocket()
的第一个参数,该参数将失败。您确实检查了该错误,但没有报告失败的原因,否则您就会知道由于传递了无效的套接字而失败,错误代码为 WSAENOTSOCK
(10038)。
尝试更像这样的事情:
for(char Index = 0; Index < MAX_CLIENTS; ++Index)
{
if (ClientSockets[Index] == INVALID_SOCKET)
{
AddressSize = sizeof(Address);
ClientSockets[Index] = accept(serverSocket,(sockaddr *)&Address,&AddressSize);
if (ClientSockets[Index] != INVALID_SOCKET)
{
unsigned long iMode = 1;
if (ioctlsocket(ClientSockets[Index],FIONBIO,&iMode) != SOCKET_ERROR)
{
Error("Making client socket unblocking has failed.\n");
closesocket(ClientSockets[Index]);
ClientSockets[Index] = INVALID_SOCKET;
continue;
}
// use ClientSockets[Index] as needed ...
}
}
}
或者:
AddressSize = sizeof(Address);
SOCKET clientSocket = accept(serverSocket,&AddressSize);
if (clientSocket != INVALID_SOCKET)
{
unsigned long iMode = 1;
if (ioctlsocket(clientSocket,&iMode) != SOCKET_ERROR)
{
Error("Making client socket unblocking has failed.\n");
closesocket(clientSocket);
}
else
{
int Index;
for(Index = 0; Index < MAX_CLIENTS; ++Index)
{
if (ClientSockets[Index] == INVALID_SOCKET)
break;
}
if (Index == MAX_CLIENTS)
{
Error("No room for client socket.\n");
closesocket(clientSocket);
}
else
{
ClientSockets[Index] = clientSocket;
// use clientSocket as needed ...
}
}
}