作者在博客中提及 Windows 上偶尔出现的网络相关问题,以 curl 连接本地主机为例。
- 问题表现:curl 连接 Windows 上的本地主机 localhost 速度很慢,需超过 200 毫秒,而其他系统只需几微秒。
- 连接过程:curl 先将 localhost 解析为 ::1 和 127.0.0.1,在同时有 IPv6 和 IPv4 地址可连接且主机支持双栈时,先尝试 IPv6 连接,若 200 毫秒内未成功则开始 IPv4 连接,这是 Happy Eyeballs 方式。其他系统在 IPv6 连接失败后会立即切换到 IPv4 连接,而 Windows 中 TCP SYN 发送到无监听端口时,客户端 TCP 栈不会立即返回错误,而是等待并多次重发 SYN 数据包,导致连接延迟,即使是仅 IPv4 的服务在默认有 IPv6 地址时也会延迟 200 毫秒。
- 与其他系统对比:其他系统 IPv6 连接失败会立即切换到 IPv4 连接,而 Windows 不会,这导致连接速度差异很大。
- 相关规范:根据解释 Windows TCP 行为的资源,此行为不违反 RFC 793,但其他系统和 TCP 栈无此行为。
- 解决办法:curl 无法在后台识别此问题,不能调整代码使其在 Windows 上早期出错。可通过修改 Windows 注册表中的
TcpMaxConnectRetransmissions键来改变行为,但需谨慎,也可通过设置–happy-eyeballs-timeout-ms为 0 来减轻 curl 的 200 毫秒延迟,或使用–ipv4强制仅使用 IPv4 连接。若不修改注册表且连接无监听端口的服务器,没有好的解决办法,只能接受 Windows 可能浪费数秒的事实。此行为在现代 Windows 版本中已得到验证。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。