一台主机上只能保持最多 65535 个 TCP 连接吗?
一台主机最多只能保持 65535 个 TCP 连接吗?小 G 先给结论:不是。
65535 这个数字来自端口号范围。TCP 首部里的源端口和目的端口字段都是 16 位,可以表示 0~65535,一共 2^16 = 65536 个取值。65535 是最大端口号,不是连接数上限。
但 TCP 连接数和端口号数不是一回事。要搞清楚这个问题,得从 TCP 连接是怎么被标识的开始讲。
TCP 连接靠四元组来区分
TCP 连接不是靠“本地端口”唯一标识,而是靠四元组标识:
源 IP、源端口、目的 IP、目的端口只要四元组不同,内核就可以把它们识别为不同连接。
为了避免混淆,下面统一用客户端发起连接时的视角来写四元组:(客户端 IP, 客户端端口, 服务端 IP, 服务端端口)。
假设服务器 IP 是 192.168.1.100,监听端口 8080:

- 客户端 A(
10.0.0.1:50000)连过来 → 四元组(10.0.0.1, 50000, 192.168.1.100, 8080) - 客户端 A(
10.0.0.1:50001)再连过来 → 四元组(10.0.0.1, 50001, 192.168.1.100, 8080) - 客户端 B(
10.0.0.2:50000)连过来 → 四元组(10.0.0.2, 50000, 192.168.1.100, 8080)
三条连接,服务端的 IP 和端口都没变,但因为客户端 IP 或端口不同,四元组各不相同,所以是三条独立的连接。
这里有个容易混淆的点:服务端 8080 端口只有一个监听 socket,但每 accept() 一次,内核就会生成一个新的已连接 socket,用四元组来区分。所以多个连接共享同一个服务端端口,完全不冲突。
为什么服务端可以超过 65535?
假设 Web 服务监听 192.168.1.100:443,服务端 IP 和端口固定,但客户端 IP 和端口会变化。比如 (10.0.0.1, 50001, 192.168.1.100, 443) 和 (10.0.0.2, 50001, 192.168.1.100, 443) 的服务端端口都是 443,但四元组不同,所以是两条不同 TCP 连接。
纯从 IPv4 四元组组合看,固定服务端 IP 和端口后,客户端 IP 理论上有 2^32 种可能,客户端端口有 2^16 种可能,理论组合数非常大。
真实上限来自资源和配置。
真正的限制是什么?
1、文件描述符(File Descriptor,FD)和内存。
在 Linux 里,socket 也是文件。对应用进程来说,accept() 后的每条已建立连接通常对应一个 socket FD;监听 socket 本身也占一个 FD。还没被 accept() 的连接会先停留在内核队列里,不应简单都算成应用已持有的 FD。
进程可打开文件数不够时,常见报错是 Too many open files。
每条 TCP 连接都需要内核维护 socket、TCP 控制块、发送缓冲区、接收缓冲区等数据。连接空闲时开销较小,一旦有数据收发,缓冲区和应用对象也会继续占内存。
不建议死记“一个连接占多少 KB”。这个值会受内核版本、socket 选项、缓冲区大小和业务收发情况影响。
2、握手队列和 accept 速度。
Linux 实际上维护两个队列:
- SYN 队列(半连接队列):收到 SYN、发出 SYN-ACK、尚未完成三次握手的连接,受
tcp_max_syn_backlog限制,实际大小还会结合somaxconn和listen()backlog 计算。 - accept 队列(全连接队列):已完成握手、等待应用
accept()的连接,上限为min(listen(fd, backlog), net.core.somaxconn)。
它们影响的是连接建立阶段的排队和丢弃,不是 ESTABLISHED 连接总数的简单上限。
半连接队列溢出时,Linux 可以启用 SYN Cookie 机制:服务端把必要信息编码进 SYN-ACK 的序列号,不在本地保留完整的半连接状态,收到合法 ACK 后再重建连接信息。SYN Cookie 是防护手段,不是扩容手段。
全连接队列溢出时,行为取决于 tcp_abort_on_overflow:默认值 0 时,服务端会丢弃客户端发来的 ACK,让客户端重传,服务端有机会重传 SYN-ACK;设为 1 时,直接回复 RST,快速失败。生产环境通常保持默认值 0,避免误拒正常连接。排查全连接队列溢出可以用 ss -ltn:如果 Recv-Q 长时间接近 Send-Q,说明 accept 不够及时,要检查应用线程池是否卡住或 backlog 配置是否过小。
3、CPU、网卡和业务处理能力。
空闲长连接主要考验内存、FD 上限、内核连接表和连接保活策略;活跃连接还会带来系统调用、加解密、协议解析、线程调度和网卡中断等压力。
客户端为什么更容易撞到端口限制?

服务端不是 65535 上限,但客户端访问同一个目标时,临时端口可能先耗尽。
例如客户端固定为 192.168.1.10,不断连接 10.0.0.1:443。这时目的 IP、目的端口、源 IP 都固定,只剩源端口可变。源端口用完后,就无法再创建新四元组。
Linux 自动分配临时端口范围可以这样看:
sysctl net.ipv4.ip_local_port_rangeMac 下可以这样查看:

很多 Linux 环境默认临时端口范围是 32768 60999,大约 2.8 万个端口;实际值以 sysctl net.ipv4.ip_local_port_range 输出为准,且不是全部 0~65535 都会自动拿来做临时端口。
看到 Cannot assign requested address / EADDRNOTAVAIL、大量 connect 失败,且目标 IP:Port 很集中时,要怀疑临时端口耗尽或 TIME_WAIT 堆积。
NAT 网关这层也可能先顶不住
还有一种情况容易被忽略:很多内网机器并不是直接访问公网,而是先经过 NAT 网关。
NAT 做的事情是把内网地址转换成公网地址。比如内网机器 192.168.1.10:50000 访问外部服务时,NAT 可能会改成 203.0.113.1:40000,并在本地记录这条映射。响应包回来后,再根据映射关系转发回原来的内网机器。
如果大量内网机器共享同一个公网 IP,并集中访问同一个外部 IP:Port,NAT 侧可用的公网源端口数量就会成为限制因素。如果目标分散,端口复用空间会更大。端口不够只是其中一类问题,NAT 设备的连接跟踪表、CPU、内存也可能先到瓶颈。
所以排查连接数问题时,不要只盯着客户端和服务端,链路中间的 NAT 网关也要看。
常见的 NAT 侧排查指标包括:NAT 连接跟踪表使用率、SNAT 端口使用率、单公网 IP 到单目标的连接数,以及 NAT 设备的 CPU、内存、丢包和连接创建速率。如果 NAT 确实成了瓶颈,可以考虑增加公网 IP、拆分出口或做连接复用。
TIME_WAIT 会怎样影响连接数?

典型情况下,主动关闭连接的一方会进入 TIME_WAIT——因为它需要在发送最后一个 ACK 后等待一段时间,防止最后 ACK 丢失以及旧报文影响后续连接。(同时关闭场景下,双方都会进入 TIME_WAIT,不过日常碰到的绝大多数是前者。)
问题在于,TIME_WAIT 会让对应连接在一段时间内不能被随意复用。对客户端高频短连接同一目标来说,可用临时端口会被大量 TIME_WAIT 消耗,从而更容易撞到端口上限。
这也是为什么高并发调用优先建议使用连接池和 HTTP keep-alive,从源头减少短连接创建。
说到连接复用,很多人分不清 TCP Keepalive 和 HTTP Keep-Alive,其实它们解决的问题完全不同。
简单说:HTTP Keep-Alive 管的是“一条连接最多用多久、服务多少次请求”,TCP Keepalive 管的是“如果长时间没数据,检查一下对方是不是已经消失了”。两者互不干扰,也不能互相替代。详细介绍可以看这篇文章:TCP Keepalive 和 HTTP Keep-Alive 有什么区别?。
至于内核参数,别一看到 TIME_WAIT 多就急着改。
tcp_tw_reuse 要结合内核版本、业务场景和真实的端口耗尽证据来看,不适合当成万能优化项。tcp_tw_recycle 更不用碰了,Linux 4.12 之后已经被移除。
也别想着清理 TIME_WAIT。它不是脏东西,而是 TCP 协议里的正常机制。
看到 TIME_WAIT 数量很多,第一反应应该是回到业务链路看问题:是不是一直在创建短连接?连接池有没有生效?HTTP keep-alive 有没有打开?客户端是不是每次请求完都主动断开?
生产环境里很常见的一个坑,就是连接池没配好,最后把临时端口耗光了。
比如:
- HTTP 客户端没开 keep-alive,也没用连接池,每次请求都新建连接,请求完就关,
TIME_WAIT很快堆起来。 - 连接池最大连接数、每个目标地址的连接数配置太小,导致连接一直被创建和销毁。
- DNS 最后解析到单个 IP,请求目标太集中,四元组里主要只剩源端口在变,更容易把端口打满。
排查这类问题,优先修连接复用。确认连接池、keep-alive、超时和关闭策略都没问题之后,再考虑扩大临时端口范围,或者增加源 IP。不要一上来就改内核参数。

排查时可以用 ss -ant 统计各 TCP 状态数量,ss -ant state time-wait | awk 'NR>1 {print $5}' | sort | uniq -c | sort -nr | head 查看 TIME_WAIT 集中在哪些目标,ss -ltn 查看监听 socket 的 accept queue 堆积情况。看到 TIME_WAIT 集中在某个远端服务,检查短连接和连接池;看到 CLOSE_WAIT 集中在某个本地进程,优先查应用代码有没有正确关闭连接。
回到问题
一台主机最多只能保持 65535 个 TCP 连接吗?
答案是:不能这么理解。
65535 对应的是端口号范围,不是 TCP 连接数上限。TCP 连接靠四元组区分:源 IP、源端口、目的 IP、目的端口。服务端监听同一个端口时,只要客户端 IP 或客户端端口不同,连接就可以继续增加。
不过,理论上能区分出来,不代表机器一定扛得住。实际连接数通常会被文件描述符、内存、CPU、网卡、应用处理能力、握手队列等资源限制住。客户端如果频繁短连接访问同一个目标,还会碰到临时端口和 TIME_WAIT 的压力;如果中间经过 NAT,还要看 NAT 网关能不能撑住。
小 G 这里再压缩成一句话:服务端连接数主要看机器资源,客户端连同一个目标主要看临时端口,中间有 NAT 时还要看 NAT 网关。65535 只是端口号上限,不是所有 TCP 连接的上限。
