首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WINSOCK -在不存在的IP上设置连接尝试的超时?

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

Stack Overflow用户
提问于 2011-06-01 09:37:13
回答 3查看 26.6K关注 0票数 18

我正在C++中开发一个RTSP源过滤器,我正在使用WINSOCK2.0-阻塞套接字.

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

代码语言:javascript
复制
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地址,并试图连接它,它在返回SOCKET_ERROR之前挂起大约10秒钟。所以,如果网络上不存在IP,SO_RCVTIMEO就会被忽略.

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

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

我的问题的答案

因为我使用阻塞套接字,所以调用connect()块,直到连接建立为止,或者连接因为主机没有响应而失败,或者它拒绝连接。如果我将套接字的超时设置为3秒,并尝试连接到一个不存在的主机,我的pc (客户端)将发送带有SYN标志的TCP数据包,以启动三次握手。通常,主机(如果向上)将使用包含ACK和SYN标志集的TCP数据包进行响应,然后客户端(me)将发送带有ACK标志集的TCP数据包。然后连接就完成了。但是,如果主机关闭,并且发送了SYN,客户端等待3秒超时过期,然后再试一次,直到到达TcpMaxConnectRetransmissions (微软文章)注册表设置,因为主机可以启动,但SYN数据包可能丢失.我的Windows将此设置设置为4,所以每次尝试发送SYN时,它都等待3秒,当第四次尝试失败时,它返回SOCKET_ERROR (12秒后),并将WSAETIMEDOUT设置为最后一个WSA错误。

解决这一问题的方法是使用非阻塞套接字,并按照Martin的建议手动测量连接尝试时间(因为现在connect()不会阻塞)。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-01 09:48:32

咬住子弹。远程IP可能没有运行PING服务器,或者PING可能被某个路由器阻塞,所以没有帮助。你不能等10秒,然后再做任何错误指示吗?

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

票数 2
EN

Stack Overflow用户

发布于 2011-06-01 10:35:51

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

票数 1
EN

Stack Overflow用户

发布于 2013-04-04 08:37:51

在cmd中,您可以使用“ping -w 100 -n 1 192.168.1.1”这样的超时来平分ip。

它将在100 it内返回。

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

在c++中

代码语言:javascript
复制
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;
} 
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6199122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档