首页 文章

WINSOCK - 为非现有IP上的连接尝试设置超时?

提问于
浏览
17

我正在用C开发一个RTSP源过滤器,我正在使用WINSOCK 2.0 - 阻塞套接字 .

当我创建一个阻塞套接字时,我将其 SO_RCVTIMEO 设置为3秒,如下所示:

int ReceiveTimeout = 3000; 
int e = setsockopt(Socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&ReceiveTimeout, sizeof(int));

我的过滤器尝试连接到 IP_ADDRESS:554 (554是RTSP服务器端口) . 如果有一台服务器在端口554上侦听该IP,一切顺利,但是:

  • 如果我的过滤器创建了一个 existing IP address 的套接字,但是在一个没有人监听的随机端口上, connect() 等待3秒并返回 WSAETIMEDOUT . 所以在3秒后,我知道提供的URL很糟糕 .

  • 如果我的过滤器为 non existing IP address 创建了一个套接字,并尝试连接它,它会在返回SOCKET_ERROR之前挂起大约10秒钟 . 因此,如果网络上不存在IP, SO_RCVTIMEO 将被忽略...

QUESTION: 在第二种情况下,如何设置非现有IP的超时?我是否需要首先发送ICMP PING以查看IP是否存在,或执行其他类似的检查?

任何帮助将不胜感激 . 感谢名单 . :)

THE ANSWER TO MY PROBLEM

因为我正在使用阻塞套接字,所以调用 connect() 块,直到 Build 连接,或者连接失败,因为主机没有响应,或者它拒绝连接 . 如果我设置socket 's timeout to be 3 seconds, and try to connect to a host that doesn' t存在,我的pc(客户端)将发送设置了 SYN 标志的TCP数据包,以启动Threeway握手 . 通常,主机(如果启动)将使用设置了 ACKSYN 标志的TCP数据包进行响应,然后,client(me)将发送设置了 ACK 标志的TCP数据包 . 然后 Build 连接 . 但是如果主机已关闭,并且 SYN 已发送,则客户端将等待3秒超时,然后再尝试AGAIN和AGAIN,直到达到 TcpMaxConnectRetransmissionsMICROSOFT ARTICLE)注册表设置,因为主机可以是UP但是 SYN 数据包可能会丢失...我的Windows XP将此设置设置为4,我猜,所以每次尝试发送 SYN 时,等待3秒,当第四次尝试失败时,它返回 SOCKET_ERROR (12秒后),将 WSAETIMEDOUT 设置为最后一个WSA错误 .

解决这个问题的方法是使用非阻塞套接字,并尝试手动测量连接尝试时间(因为现在 connect() 不会阻塞),就像Martin James所说的那样 .

另一种方法是摆弄注册表,这是最后的手段......

3 回答

  • 0

    硬着头皮 . 远程IP可能没有运行PING服务器或PING可能被某些路由器阻止,所以没有帮助 . 你能不能等待10秒然后做出你使用的任何错误指示?

    如果你必须在3秒后超时尝试连接,你可以自己计时 .

  • 2

    实际上,Berkeley套接字没有超时连接,所以你无法设置它 . ICMP PING没有帮助,我不知道为什么,但如果主机不存在,你花费大约1秒钟与PING . 尝试使用ARP进行检测是否存在主机 .

  • 2

    从cmd你可以用这样的'ping -w 100 -n 1 192.168.1.1'超时ping ip

    它将在100毫秒内返回

    您可以通过'echo%errorlevel%0 = ok,1 =失败检查返回码,然后您知道是否应该尝试连接

    在c

    bool pingip_nowait(const char* ipaddr)
    {
        DWORD exitCode;
    
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
        si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
        si.hStdOutput =  GetStdHandle(STD_OUTPUT_HANDLE);
        si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
        si.wShowWindow = SW_HIDE;
    
        CString cmd = "ping -w 100 -n 1 ";
        cmd += ipaddr;
        if (!CreateProcess(NULL,
            cmd.GetBuffer(),
            NULL,
            NULL,
            FALSE,
            0,
            NULL,
            NULL,
            &si,
            &pi)) {
                TRACE("ERROR: Cannot launch child process\n");
                return false;
        }
    
        // Give the process time to execute and finish
        WaitForSingleObject(pi.hProcess, 200L);
    
        if (GetExitCodeProcess(pi.hProcess, &exitCode))
        {
            TRACE("ping returned %d\n", exitCode);
            // Close process and thread handles. 
            CloseHandle( pi.hProcess );
            CloseHandle( pi.hThread );
            return exitCode==0 ? true : false;
        }
        TRACE("GetExitCodeProcess() failed\n");
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
        return false;
    }
    

相关问题