Setting winsock select timeout accurately

13,146

Solution 1

why is this so?

This is per defintion.

Verbatim from MSDN:

tv_sec Time interval, in seconds.

tv_usec Time interval, in microseconds. This value is used in combination with the tv_sec member to represent time interval values that are not a multiple of seconds.

Solution 2

The problem is with tv.tv_usec; tv_usec as per man page is of type 'long'. The value (2400000000) is out of range of long and that is the reason you are getting such select system behavior.

If you want select to wait for 40 min then make sure you are using tv.tv_sec.

Share:
13,146
shawn
Author by

shawn

Updated on June 21, 2022

Comments

  • shawn
    shawn almost 2 years

    I am trying to make my accept call timeout after a specified time period and I tried following the suggestion here:

    Winsock accept timeout

    in which case I pass a TIMEVAL struct to select when I call it, problem is when I set tv.tv_usec to say around 40 minutes or so, the select call times out immediately instead of waiting for the 40 minutes I specified. MSDN states that the timeout for select is the maximum time that it will wait, how do I make it such that select or accept for that matter waits for a specific time period before timing out?

    #define WIN32_LEAN_AND_MEAN
    
    #include <Windows.h>
    
    #include <WinSock2.h>
    #include <Ws2tcpip.h>
    
    #include <cstdio>
    #include <tchar.h>
    
    VOID _tmain( int argc, TCHAR *argv[] )
    {
        WSADATA wsaData = { 0 };
        ADDRINFOA hINTs = { 0 };
        PADDRINFOA pResult = NULL;
        SOCKET hServerSocket = INVALID_SOCKET,
               hClientSocket = INVALID_SOCKET;
        TIMEVAL tv = { 0 };
        INT iReturnStatus = -1;
        DWORD dwRecvTimeout = 30000, // Milliseconds
              dwSendTimeout = 30000; // Milliseconds
        fd_set readFDs = { 0 };
    
        if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) )
        {
            _tprintf_s( TEXT( "WSAStartup Failed\n" ) );
            return;
        }
    
        ZeroMemory( &hINTs, sizeof( hINTs ) );
        hINTs.ai_family = AF_INET;
        hINTs.ai_socktype = SOCK_STREAM;
        hINTs.ai_protocol = IPPROTO_TCP;
        hINTs.ai_flags = AI_PASSIVE;
        if ( getaddrinfo( NULL, TEXT( "9001" ), &hINTs, &pResult ) )
        {
            WSACleanup();
            _tprintf_s( TEXT( "getaddrinfo Failed\n" ) );
            return;
        }
    
        if ( ( hServerSocket = socket( pResult -> ai_family, pResult -> ai_socktype, pResult -> ai_protocol ) ) == INVALID_SOCKET )
        {
            freeaddrinfo( pResult );
            WSACleanup();
            _tprintf_s( TEXT( "socket Failed\n" ) );
            return;
        }
    
        int iResult = bind( hServerSocket, ( pResult -> ai_addr ), pResult -> ai_addrlen );
        if ( iResult == SOCKET_ERROR )
        {
            freeaddrinfo( pResult );
            closesocket( hServerSocket );
            WSACleanup();
            _tprintf_s( TEXT( "bind Failed\n" ) );
            return;
        }
        freeaddrinfo( pResult );
    
        if ( listen( hServerSocket, SOMAXCONN ) )
        {
            closesocket( hServerSocket );
            WSACleanup();
            _tprintf_s( TEXT( "listen Failed\n" ) );
            return;
        }
    
        hClientSocket = INVALID_SOCKET;
    
        for ( ;; )
        {
            tv.tv_usec = 2400000000; // microseconds
            FD_ZERO( &readFDs );
            FD_SET( hServerSocket, &readFDs );
            _tprintf( "select()\n" );
            iReturnStatus = select( 0, &readFDs, NULL, NULL, &tv );
    
            // Select Error
            if ( iReturnStatus == SOCKET_ERROR )
            {
                _tprintf( "select Failed\n" );
            }
            // Select Success
            else if ( iReturnStatus )
            {
                // Connection Established On Server Socket
                if ( FD_ISSET( hServerSocket, &readFDs ) )
                {
                    // Accept Client Connection
                    hClientSocket = accept( hServerSocket, NULL, NULL );
                    if ( hClientSocket == INVALID_SOCKET )
                    {
                        _tprintf( "accept Failed\n" );
                    }
                    else
                    {
                        // Set Recv Timeout
                        setsockopt( hClientSocket, SOL_SOCKET, SO_RCVTIMEO, ( const char * ) &dwRecvTimeout, sizeof( dwRecvTimeout ) );
    
                        // Set Send Timeout                 
                        setsockopt( hClientSocket, SOL_SOCKET, SO_SNDTIMEO, ( const char * ) &dwSendTimeout, sizeof( dwSendTimeout ) );
    
                        // Process Client Request(s)
                        // HandleConnection( ClientSocket );
                    }
                }
                // Connection Established On Unknown Socket
                else
                {
                    _tprintf( "Invalid Socket Returned\n" );
                }
            }
            // Select Timeout
            else
            {
                _tprintf( "select Timeout\n" );
            }
    
        }
        if ( hServerSocket != INVALID_SOCKET )
            closesocket( hServerSocket );
    
        return;
    }
    
  • Viswesn
    Viswesn almost 12 years
    the range of long is -2147483648 and 2147483647.
  • alk
    alk almost 12 years
    I wonder if tv_usec=2147483647 really would lead to a time out of 2147s, but 0.483647s ... - no win32 available right now to check.