Winsock 的 connect() 函数中的超时

Timeout in connect() function from Winsock

本文关键字:超时 函数 connect Winsock      更新时间:2023-10-16
当我

从Winsock调用connect((函数时,有什么方法可以减少超时吗?我想差不多是30秒,我想放5秒。

最简单的方法是在连接时以非阻塞模式使用套接字,并使用超时为 5 秒的select()来检查套接字是否可写。select()退出后,连接已建立或未建立。 如果没有,请考虑连接超时,并根据需要执行错误处理。

你也可以调用 ConnectEx(( 函数,并通过预先创建的事件向它传递 OVERLAPPED.hEvent 结构,你可以根据需要使用 WaitForSingleObject(( 等待

ConnectEx(( 仅在 WindowsXP 及更高版本中可用...

//The HANDLE Socket MUST BE pre-bound with Bind() before calling this function
int ConnectWithTimout(HANDLE Socket, UINT remIP, WORD remPort, UINT milliseconds)
{
    int iRes, Result;
    UINT OptVal, Flags;
    OVERLAPPED Overlapped;
    sockaddr_in socket_info;

    Result= ERROR_UNEXP_NET_ERR;
    ZeroMemory(&socket_info, sizeof(socket_info));
    ZeroMemory(&Overlapped, sizeof(Overlapped));
    socket_info.sin_addr.S_addr = htonl(remIP);
    socket_info.sin_port = htons(remPort);
    socket_info.sin_family = AF_INET;
    Overlapped.hEvent = WSACreateEvent(); 
    if ( ConnectEx(Socket, &socket_info, sizeof(socket_info), NULL, 0, NULL, &Overlapped) )
        printf("WOW! Connection succeeded immediatelyn");
    else
    {
        iRes = WSAGetLastError();
        if (iRes == ERROR_IO_PENDING)
        {
            iRes = WaitForSingleObject(Overlapped.hEvent, milliseconds);  //Wait for x milliseconds to connect
            if (iRes == WAIT_OBJECT_0)
            {
                if (!WSAGetOverlappedResult(socket, &Overlapped, &OptVal, FALSE, Flags))
                {
                    iRes = WSAGetLastError();
                    if (iRes == WSAEADDRINUSE)
                        DoError("WSAGetOverlappedResult() reported that the requested local address is already in use or in a TIME_WAIT state")
                    else
                        DoError("WSAGetOverlappedResult() failed with error: ", iRes);
                }
                else
                {
                    OptVal = 1;
                    iRes = setsockopt(Socket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, PCHAR(&OptVal), sizeof(OptVal));
                    if (iRes == SOCKET_ERROR)
                        DoError("setsockopt(SO_UPDATE_CONNECT_CONTEXT) failed with error: ", WSAGetLastError() );
                    printf("Connected to %s : %sn", inet_ntoa(socket_info.sin_addr), itoa(ntohs(socket_info.sin_port)));
                    Result=NO_ERROR;
                }
            }
            else
            {
                if (iRes == WAIT_TIMEOUT)
                {
                    DoWarning("ConnectEx() TIMED OUT - ", iRes);
                    Result= ERROR_TIMEOUT;
                }
                else
                    DoError("ConnectEx() failed with error: ", iRes)
            }
        }
        else if (iRes ==  WSAECONNREFUSED)  //After this error, it is OK to try to connect again on this docket.
            DoWarning("ConnectEx() failed with CONNECTION REFUSED: ", 0 )
        else if (iRes =  WSAENETUNREACH)    //After this error, it is OK to try to connect again on this docket.
            DoWarning("ConnectEx() failed with NETWORK UNREACHABLE: ", 0 )
        else if (iRes =  WSAETIMEDOUT)  //After this error, it is OK to try to connect again on this docket.
        {
            DoWarning("ConnectEx() TIMED OUT Immediately:", 0 );
            Result= ERROR_TIMEOUT;
        }
        else
            DoError("ConnectEx() failed with unexpected error: ", iRes )
    }

    WSACloseEvent(Overlapped.hEvent);
    return Result;
}