在阅读有关端口耗尽的文章时,我经常看到它考虑了 tcp 连接的四倍(源 ip、源端口、目标 ip、目标端口)。因此,看起来,如果端口范围为 20000(40000 到 60000),并且在同一台机器上使用两个客户端,使用相同的源地址和目标地址,以目标端口 8088 和 8087 为目标,我应该能够打开 40000 个连接。但是,在我的测试中情况并非如此。即使在这种配置下,我也只能打开 20000 个连接。我转储了 ss -s 的输出并按源端口对其进行排序。以下是摘录:
CLOSE-WAIT 26378 0 172.24.131.110 40001 172.24.131.97 9088
CLOSE-WAIT 25029 0 172.24.131.110 40002 172.24.131.97 9087
CLOSE-WAIT 23840 0 172.24.131.110 40003 172.24.131.97 9087
CLOSE-WAIT 25207 0 172.24.131.110 40004 172.24.131.97 9087
CLOSE-WAIT 25572 0 172.24.131.110 40005 172.24.131.97 9088
CLOSE-WAIT 26334 0 172.24.131.110 40006 172.24.131.97 9087
CLOSE-WAIT 27089 0 172.24.131.110 40007 172.24.131.97 9087
CLOSE-WAIT 23860 0 172.24.131.110 40008 172.24.131.97 9088
CLOSE-WAIT 25463 0 172.24.131.110 40009 172.24.131.97 9087
CLOSE-WAIT 26603 0 172.24.131.110 40010 172.24.131.97 9088
CLOSE-WAIT 25436 0 172.24.131.110 40011 172.24.131.97 9087
ESTAB 0 0 172.24.131.110 40012 172.24.131.97 9087
CLOSE-WAIT 25042 0 172.24.131.110 40013 172.24.131.97 9087
CLOSE-WAIT 25738 0 172.24.131.110 40014 172.24.131.97 9087
CLOSE-WAIT 27363 0 172.24.131.110 40015 172.24.131.97 9088
CLOSE-WAIT 25860 0 172.24.131.110 40016 172.24.131.97 9088
它会一直持续到达到值 60000。源端口永远不会被使用两次,就好像值池实际上是通用的一样。是这种情况还是我在某处缺少配置标志?
内核版本是 4.15.0-144-generic。端口范围在这里确实受控制:如果我将端口范围更改为 40000-50000,则只有 10000 个可能的连接。测试的客户端和服务器是网络测谎工具。
答案1
好吧,事实上我想我有答案了,我使用的客户端使用 bind + connect 创建连接,而不是仅仅使用 connect。这是一个 strace 转储:
bind(1490, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("172.24.131.110")}, 16) = 0
getsockname(1490, {sa_family=AF_INET, sin_port=htons(50929), sin_addr=inet_addr("172.24.131.110")}, [16]) = 0
connect(1490, {sa_family=AF_INET, sin_port=htons(9088), sin_addr=inet_addr("172.24.131.97")}, 16) = -1 EINPROGRESS (Operation now in progress)
据我理解,在这种情况下,您确实会返回到不同客户端的唯一池,因为在绑定时您没有有关远程端的任何信息。
关于此主题的一个有用链接:https://idea.popcount.org/2014-04-03-bind-before-connect/