c++ - 准确设置 winsock 选择超时

标签 c++ c windows winapi winsock

我试图在指定的时间段后让我的接受调用超时,我尝试按照此处的建议进行操作:

Winsock accept timeout

在这种情况下,我在调用它时传递了一个 TIMEVAL 结构来选择,问题是当我将 tv.tv_usec 设置为大约 40 分钟左右时,选择调用立即超时,而不是等待我指定的 40 分钟。 MSDN 声明 select 的超时是它将等待的最长时间,我如何使 select 或 accept 在超时前等待特定的时间段?

#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;
}

最佳答案

why is this so?

这是每个定义。

逐字记录来自 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.

关于c++ - 准确设置 winsock 选择超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10990533/

相关文章:

c - TraceFS : ioctl: inappropriate ioctl for device

windows - Windows 上的 symfony2 assetics yui 压缩器(路径语法)

c++ - 如何使用 boost::bind 将返回 int 的函数转换为返回 bool 的函数?

c++ - 在 C++ 中原则上不可能进行严格的模板评估吗?

c++ - 将 __COUNTER__ 宏重置为零

c - 您必须选择一个主机应用程序到 "run"一个库

c++ - Ubuntu中如何通过语音命令生成键盘、鼠标事件

python - 是否可以打开 PyGTK 对象?

ruby - 如何使 Ruby 文件作为可执行文件运行?

python - 在单核上运行的 python 3.x/Windows 7 上的多进程 map-reduce