在 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 堆栈可以配置这些端口范围和时序:
- HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort 影响端口范围
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay 影响套接字停留的时间。
进行交互式会话时,您可以使用 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'
我们的 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 堆栈可以配置这些端口范围和时序:
- HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort 影响端口范围
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay 影响套接字停留的时间。
进行交互式会话时,您可以使用 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'