如果我在不同的线程中将 tcp 套接字更改为非阻塞,我的程序在 Sleep() 之后返回 1

问题描述

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

    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 ...
        }
    }
}