如何让 Windows 在 TCP 连接尝试后遵守 ICMP 连接拒绝消息

如何让 Windows 在 TCP 连接尝试后遵守 ICMP 连接拒绝消息

我们有一个工具,用于通过 TCP 远程管理服务器进程。该工具的一项功能是,通过在给定的时间段内循环尝试连接服务器来检查服务器是否正在运行。

当我们使用该工具检查服务器是否未运行时,我们注意到 Windows 上的计时准确性非常低,例如,尝试连接死机服务器 2 秒会导致工具运行 7 秒而不是预期的 2 秒,而在 Linux 上计时精确到几毫秒。这里的问题是我们在启动脚本中使用该工具,声明服务器死机的延迟会增加启动脚本的运行时间。

事实证明,罪魁祸首似乎是 Windows TCP/IP 堆栈:在 Windows 上,尝试连接到本地端口失败需要 2-5 秒才能完成,具体取决于机器,而在 Linux 上,连接几乎是即时的。理论上,Windows 堆栈不尊重/不关心服务器返回的 ICMP 连接拒绝消息,并继续进行另一次连接尝试。

所以我的问题分为两部分:i)上述理论是否合理?ii)我如何告诉 Windows 遵守 ICMP 响应?

-- 劳里

答案1

有人回答说,服务器的实际响应是 TCP RST 而不是 ICMP 消息,但该答案现已被删除。

无论如何,我做了更多的挖掘,并查看了一些失败连接尝试的 Wireshark 痕迹:

i)响应确实是 TCP RST、ACK,而不是我最初认为的 ICMP 消息

ii)Windows TCP/IP 堆栈实现为在 RST、ACK 之后重试连接尝试,希望服务器可能在连接超时内奇迹般地重新出现 [1]

iii) 管理员可以将 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 中的 TcpMaxConnectRetransmissions 注册表项设置为低于默认值 3 (WinNT) 或 2 (Win2k) 的值。

因此,答案是调整注册表并将 TcpMaxConnectRetransmissions 降低到 0 或 1。我对这个“解决方案”的唯一问题是,AFAICT 这也会影响连接尝试,其中初始 SYN 在网络中被丢弃,在这种情况下将值设置为 0 是个坏主意,而将其设置为 1 仍会导致我的脚本的运行时间比必要的时间更长。

[1] 更多信息:http://support.microsoft.com/kb/175523

-- 劳里

相关内容