我正在用 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,则一切正常,但是:
如果我的过滤器创建一个到现有 IP 地址的套接字,但在没有人监听的随机端口上,
connect()
等待 3 秒并返回WSAETIMEDOUT
。所以 3 秒后,我知道提供的 URL 是错误的。如果我的过滤器为不存在的 IP 地址创建一个套接字并尝试连接它,它会在返回 SOCKET_ERROR 之前挂起大约 10 秒。因此,
SO_RCVTIMEO
如果网络上不存在 IP,则会被忽略...
问题: 在第二种情况下,如何为不存在的 IP 设置超时?我是否需要先发送 ICMP PING 以查看 IP 是否存在,或者执行其他类似的检查?
任何帮助将不胜感激。谢谢。:)
我的问题的答案
因为我正在使用阻塞套接字,所以调用connect()
阻塞,直到建立连接,或者连接失败,因为主机没有响应,或者它拒绝连接。如果我将套接字的超时设置为 3 秒,并尝试连接到不存在的主机,我的电脑(客户端)将发送SYN
设置了标志的 TCP 数据包,以启动三向握手。通常,如果主机启动,将响应包含 TCP 数据包ACK
并SYN
设置标志,然后客户端(我)将发送带有ACK
标志设置的 TCP 数据包。然后建立连接。但是,如果主机关闭并SYN
发送,客户端会等待 3 秒超时到期,然后再尝试一次,再一次,直到TcpMaxConnectRetransmissions
(微软文章)注册表设置已达到,因为主机可以启动但SYN
数据包可能会丢失......我的Windows XP有这个设置为4,我猜,所以每次它尝试发送SYN
时,它等待3秒,当第四尝试失败,它返回SOCKET_ERROR
(12 秒后),并设置WSAETIMEDOUT
为最后一个 WSA 错误。
解决这个问题的方法是使用非阻塞套接字,并connect()
按照 Martin James 的建议尝试手动测量连接尝试时间(因为现在不会阻塞)。
另一种方法是摆弄注册表,这是最后的手段......