简体   繁体   English

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

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

I have a thread that accepts client connections and makes the client sockets non blocking.我有一个接受客户端连接并使客户端 sockets 非阻塞的线程。

    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");
            }

        }
    }

In the main thread I receieve packets from the clients.在主线程中,我收到来自客户端的数据包。

In the main thread after I execute Sleep() the program returns 1 and ends.在我执行 Sleep() 后的主线程中,程序返回 1 并结束。

The only thing that I found to work was removing ioctlsocket from the thread that accepts clients.我发现唯一可以工作的是从接受客户端的线程中删除 ioctlsocket。

You are using accept() incorrectly.您错误地使用accept()

The 1st parameter of accept() is an input-only parameter, specifying which listening socket to accept a pending client connection for. accept()的第一个参数是仅输入参数,指定哪个侦听套接字接受挂起的客户端连接。 That parameter is not an output parameter, like you are trying to treat it as.该参数不是 output 参数,就像您尝试将其视为一样。

You are passing ClientSockets[Index] to the 1st parameter accept() .您将ClientSockets[Index]传递给第一个参数accept() But ClientSockets[Index] is set to INVALID_SOCKET .但是ClientSockets[Index]设置为INVALID_SOCKET That will make accept() fail, but you are ignoring that error.这将使accept()失败,但您忽略了该错误。 You need to pass in the listening socket that you created earlier with socket() instead.您需要传入您之前使用socket()创建的侦听套接字

You are not assigning the return value of accept() to ClientSockets[Index] , so it remains set to INVALID_SOCKET .您没有将accept()返回值分配给ClientSockets[Index] ,因此它仍然设置为INVALID_SOCKET You are then passing that to the 1st parameter of ioctlsocket() , which will fail.然后,您将其传递给ioctlsocket()的第一个参数,这将失败。 You do check that error, but you are not reporting WHY it failed, otherwise you would have known that it is failing with an error code of WSAENOTSOCK (10038) due to being passed an invalid socket.您确实检查了该错误,但您没有报告它失败的原因,否则您会知道它由于传递了无效的套接字而失败,错误代码为WSAENOTSOCK (10038)。

Try something more like this instead:尝试更多类似的东西:

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

Alternatively:或者:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM