如果我在另一个线程中将 tcp 套接字更改为非阻塞,我的程序 returns 1 在 Sleep() 之后

My program returns 1 after Sleep() if I change a tcp socket to non blocking in a different thread

我有一个线程接受客户端连接并使客户端套接字非阻塞。

    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() 后的主线程中,程序 returns 1 结束。

我发现唯一有用的是从接受客户端的线程中删除 ioctlsocket。

您使用 accept() 不正确。

accept() 的第一个参数是一个仅供输入的参数,指定要为哪个 侦听套接字 接受挂起的客户端连接。该参数不是输出参数,就像您试图将其视为一样。

您正在将 ClientSockets[Index] 传递给第一个参数 accept()。但是 ClientSockets[Index] 设置为 INVALID_SOCKET。这将使 accept() 失败,但您忽略了该错误。您需要传入之前使用 socket() 创建的 listening socket

您没有将 accept()return 值 分配给 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, (sockaddr *)&Address, &AddressSize);
if (clientSocket != INVALID_SOCKET)
{
    unsigned long iMode = 1;
    if (ioctlsocket(clientSocket, FIONBIO, &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 ...
        }
    }
}