每个主机的 TCP 源端口是否必须是唯一的?

每个主机的 TCP 源端口是否必须是唯一的?

我了解到 TCP 连接由三元组 (源 IP、源端口、目标 IP、目标端口) 标识。理论上,因此应该可以让来自 host1:port1 的客户端连接到 server1:port1,同时另一个客户端 (在 host1 上运行) 从 host1:port1 连接到 server2:port1。

我已经用 Java 进行了一些测试,到目前为止似乎是可行的。

但是,我多次读到,源端口对于主机地址必须是唯一的,这基本上意味着并发传出 TCP 连接数最多为 65536 个。这是真的吗?

更新:这是我的 Java 代码。这似乎有效,并且 netstat -t 清楚地显示从端口 9990 发起活动传出连接(一个到 9997,一个到 9998)。至少在现代 Linux 上,这似乎是可能的?

Socket s1 = new Socket();
s1.setReuseAddress(true);
SocketAddress saremote = new InetSocketAddress("localhost",9999);
SocketAddress salocal = new InetSocketAddress("localhost",9990);
s1.bind(salocal);
s1.connect(saremote);


Socket s2 = new Socket();
s2.setReuseAddress(true);
SocketAddress saremote2 = new InetSocketAddress("localhost",9998);
SocketAddress salocal2 = new InetSocketAddress("localhost",9990);
s2.bind(salocal2);
s2.connect(saremote2);

netstat -t 输出(截断):

tcp6       0      0 localhost:9990          localhost:9998          CONNECTED 
tcp6       0      0 localhost:9990          localhost:9999          CONNECTED 

答案1

这不是 TCP 的要求。就 TCP 而言,只有源 IP、源端口、目标 IP 和目标端口的组合才需要唯一。然而,实际上,大多数 TCP API 不提供任何方法来创建具有相同源端口的多个连接,除非它们具有不同的源 IP 地址。

答案2

这是实际的最大值,通常更低。例如,Linux 使用net.ipv4.ip_local_port内核参数来定义用于出站连接的端口。这通常是这样的

sysctl net.ipv4.ip_local_port_range 32768 to 61000

您可以使用 sysctl 增加可用数量,例如

sysctl -w net.ipv4.ip_local_port_range="10000 64000"

或者你可以用相同的信息编辑 /etc/sysctl.conf

net.ipv4.ip_local_port_range = 10000 65535

我发现的所有例子也都表明最小值也是 1024。

答案3

除了 Iain 的回答(上文)之外,内核可能只允许 10,000 个端口用于传出连接,理论上,适配器上每个 IP 地址至少限制为一组 XX,XXX 端口。由于 127.1 不对外开放,位于本地网络上,因此对于每个其他 IP 地址(外部的)您的 65K 端口范围内有一组传出端口。

因此,实际的传出限制是:

  With 1 IP Address: XX,XXX (or 2 x XX,XXX on internal network)
  With 2 IP addresses: 2 x XX,XXX (or 3 x XX,XXX on internal network)
  With 3 IP addresses: 3 x XX,XXX (or 4 x XX,XXX on internal network)
  etc.

为了做到这一点,你需要阅读以下答案此主题

答案4

尽管系统可能对打开的 TCP 连接数有限制,但通常对使用的端口号没有限制。但是,良好的 TCP 实现必须防止两次使用同一对套接字。(套接字 = IP 地址 + 端口)。但是,将端口分配给进程以防止窃取连接,通常的方法是请求一个空闲端口作为监听端口或传出端口。这可以防止重复的传出套接字,从而防止重复的连接。如果不使用该方法,应用程序本身必须防止创建重复的连接。

相关内容