WINSOCK-在不存在的IP上设置连接尝试超时



我正在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,一切都很顺利,但:

  1. 如果我的过滤器创建了一个到现有IP地址的套接字,但在一个没有人监听的随机端口上,connect()会等待3秒并返回WSAETIMEDOUT。所以3秒钟后,我知道提供的URL不好。

  2. 如果我的筛选器创建了一个到不存在的IP地址的套接字,并尝试连接它,它会挂起大约10秒,然后返回socket_ERROR。因此,如果网络上不存在IP,SO_RCVTIMEO将被忽略。。。

问题:在第二种情况下,如何为不存在的IP设置超时?我需要先发送ICMP PING来查看IP是否存在,还是执行类似的其他检查?

任何帮助都将不胜感激。Thanx.:)

我的问题的答案

因为我正在使用阻塞套接字,所以调用connect()块,直到建立连接,或者由于主机没有响应或拒绝连接而导致连接失败。如果我将套接字的超时设置为3秒,并尝试连接到不存在的主机,我的pc(客户端)将发送设置了SYN标志的TCP数据包,以启动三向握手。通常情况下,如果启动,主机将使用包含ACKSYN标志集的TCP数据包进行响应,然后,客户端(我)将发送设置了ACK标志的TCP数据。然后进行连接。但是,如果主机关闭,并且发送了SYN,客户端会等待,直到3秒超时到期,然后重试,再重试,直到达到TcpMaxConnectRetransmissions(MICROSOFT ARTICLE)注册表设置,因为主机可能处于UP状态,但SYN数据包可能会丢失。。。我想,我的Windows XP的这个设置是4,所以每次它尝试发送SYN时,它都会等待3秒,当第四次尝试失败时,它会返回SOCKET_ERROR(12秒后),并将WSAETIMEDOUT设置为最后一个WSA错误。

解决方法是使用非阻塞套接字,并尝试手动测量连接尝试时间(因为现在connect()不会阻塞),正如Martin James所建议的那样。

另一种方法是篡改注册表,这是最后的手段。。。

咬紧牙关。远程IP可能没有运行PING服务器,或者PING可能被某些路由器阻止,所以没有帮助。你能不能等10秒,然后用任何错误指示?

如果你必须在3秒钟后将尝试的连接超时,你可以自己超时。

实际上,Berkeley套接字没有连接超时,所以您不能设置它。ICMP PING没有帮助,我不知道为什么,但如果主机不存在,你会花大约1秒的时间使用PING。尝试使用ARP来检测主机是否存在。

从cmd,您可以在超时的情况下ping ip,如"ping-w 100-n 1 192.168.1.1"

它将在100mS 内返回

您可以通过"echo%errorlevel%0=好,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 processn");
            return false;
    }
    // Give the process time to execute and finish
    WaitForSingleObject(pi.hProcess, 200L);
    if (GetExitCodeProcess(pi.hProcess, &exitCode))
    {
        TRACE("ping returned %dn", exitCode);
        // Close process and thread handles. 
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
        return exitCode==0 ? true : false;
    }
    TRACE("GetExitCodeProcess() failedn");
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return false;
} 

最新更新