vk123
vk123

Reputation: 53

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.

    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.

The only thing that I found to work was removing ioctlsocket from the thread that accepts clients.

Upvotes: 0

Views: 63

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596672

You are using accept() incorrectly.

The 1st parameter of accept() is an input-only parameter, specifying which listening socket to accept a pending client connection for. That parameter is not an output parameter, like you are trying to treat it as.

You are passing ClientSockets[Index] to the 1st parameter accept(). But ClientSockets[Index] is set to INVALID_SOCKET. That will make accept() fail, but you are ignoring that error. You need to pass in the listening socket that you created earlier with socket() instead.

You are not assigning the return value of accept() to ClientSockets[Index], so it remains set to INVALID_SOCKET. You are then passing that to the 1st parameter of ioctlsocket(), which will fail. 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.

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

Upvotes: 1

Related Questions