在 Windows 上显示一条错误消息 "socket re-usage" 尽管没有打算这样做

On Windows shows an error message "socket re-usage" though there is no intend to do so

我们的 CI 有大量并行工作负载,我们在尝试连接到 Windows 上的(本地)服务器时在客户端上看到此错误消息:

connect() failed with #10048 - Only one usage of each socket address (protocol/network address/port) is normally permitted.

之后所有与连接相关的测试都将失败。

TCP 堆栈有 65536 个可能的端口。一个tcp连接涉及2个端口:

  • 服务器绑定的那个 - 即用于 HTTP 的端口 80
  • 客户端发起连接的源端口

根据惯例(和配置),这 65k 个端口被划分为多个范围。默认情况下,客户端端口取自高于预配置端口的上限范围。 windows net命令可以显示其当前配置状态:

netsh int ipv4 show dynamicport tcp
Protocol tcp Dynamic Port Range
---------------------------------
Start Port      : 49152
Number of Ports : 16384

因此,tcp 端口是一种有限的资源,如果大量使用,您可以 运行 摆脱它们。使情况恶化的另一件事是 套接字死后在内核中有生命:TIME_WAIT。 处于这种状态的套接字会在一段时间内徘徊,因此 TCP 堆栈可以处理迟到的包 - 默认情况下为 2 分钟 - 即使在环回接口上(SRSLY Microsoft?)。

windows IP 堆栈可以配置这些端口范围和时序:

进行交互式会话时,您可以使用 netstat or TCPView 观察您机器上已分配套接字的列表。

在非交互式脚本环境中,使用即powershell get-nettcpconnection可用于获取使用端口的统计信息。

如果您处于 CI 情况,您想知道什么时候开始新测试是安全的,您可以停止这样做,除非不超过 2/3 的客户端套接字及时等待:

Function waitForTimeWaitSockets() {
    do {
      $TimeWait = (Get-NetTCPConnection -State TimeWait | Measure-Object).Count
      if ($TimeWait -gt 10000) {
        Write-Host "waiting for connections to go away ${TimeWait}"
        Start-Sleep 20
      }
    } while ($TimeWait -gt 10000)
}

确定频繁打开和关闭套接字不是最佳实践,您应该努力重新使用连接,例如 HTTP/1.1 持久连接。

可以找到关于该主题的更多讨论 in the microsoft article 'Troubleshoot port exhaustion issues'