2. 端口概念回顾:TCP/UDP端口号、端口范围划分、端口与进程关系、端口状态详解

聊QUIC排查之前,咱们得先把端口这件事儿掰扯清楚。我见过太多人一上来就抓包、看日志,折腾半天发现连端口号是干嘛的都没搞明白。说白了,端口就是操作系统给网络进程分配的门牌号。

你想想看,一台服务器上跑着几十个服务,数据包到了网卡之后,系统怎么知道该交给谁?靠的就是端口号。IP地址找到机器,端口号找到进程,就这么简单。

2.1 端口号的范围划分

端口号是个16位的数字,范围从0到65535。这个范围被分成了三段,每段的用途不一样。我刚开始做运维那会儿,经常搞混这些段,后来踩了几次坑才记住。

范围 分类 说明 典型例子
0 - 1023 系统端口(Well-Known Ports) 需要root权限才能绑定,留给标准服务 HTTP(80)、HTTPS(443)、DNS(53)
1024 - 49151 注册端口(Registered Ports) 用户进程可用,IANA登记过的服务 MySQL(3306)、Redis(6379)
49152 - 65535 动态/私有端口(Dynamic/Private Ports) 临时使用,客户端随机分配 浏览器发请求时的临时端口
我的习惯:部署QUIC服务时,我一般选443或者UDP 443。但如果你在内网测试,建议用1024以上的注册端口,别跟系统端口抢。我曾经见过有人把QUIC绑在UDP 53上,结果跟DNS冲突,排查了一下午。

2.2 TCP与UDP端口的核心差异

很多人以为端口就是端口,TCP和UDP没区别。其实不是。TCP和UDP的端口空间是独立的。什么意思?就是TCP 443和UDP 443是两个不同的门,可以绑定不同的服务。

QUIC用的是UDP,这一点特别重要。我遇到过好几次,有人把QUIC的端口占用问题当成TCP端口冲突去查,方向完全错了。

特性 TCP端口 UDP端口
连接状态 有状态(ESTABLISHED、LISTEN等) 无状态(只有绑定和未绑定)
端口复用 SO_REUSEADDR需要谨慎使用 SO_REUSEPORT常见于多进程模型
端口扫描 三次握手可探测 无握手,探测难度大
典型应用 HTTP、SSH、数据库连接 DNS、QUIC、视频流
注意:QUIC虽然跑在UDP上,但它自己维护了连接状态。所以排查QUIC端口问题时,不能只看UDP端口是否被占用,还要看QUIC连接层有没有冲突。我曾经在排查一个QUIC服务无法启动的问题时,发现UDP端口是空闲的,但QUIC内部连接表满了,导致新连接进不来。

2.3 端口与进程的关系

端口本身不干活,干活的是进程。端口只是进程和网络之间的一个绑定关系。你可以把进程想象成一个公司,端口就是公司的前台电话。数据包打进来,前台(端口)转给对应的部门(进程)。

在Linux上,查看端口和进程的关系,最常用的命令就是ss和lsof。我个人习惯用ss,因为它更快,而且输出更清晰。

# 查看所有UDP监听端口及其对应的进程
ss -ulnp

# 查看特定端口(比如443)的占用情况
ss -ulnp sport = :443

# 查看进程ID对应的端口
ss -ulnp | grep 'pid=1234'

输出示例:

State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port   Process
UNCONN   0        0                0.0.0.0:443           0.0.0.0:*       users:(("quic-server",pid=1234,fd=7))

这里要注意,UDP的State列显示的是UNCONN,表示未连接状态。TCP的监听状态是LISTEN,这是两者在端口状态上的一个明显区别。

2.4 端口状态详解

端口状态这个概念,TCP和UDP差别很大。TCP有完整的状态机,UDP就简单得多。咱们先看TCP的,再看UDP的。

2.4.1 TCP端口状态

TCP端口的状态其实反映的是连接的状态。一个端口可以同时处于多个连接中,每个连接都有自己的状态。但端口本身也有一个监听状态。

状态 含义 常见场景
LISTEN 端口正在监听,等待连接 服务端启动后,等待客户端连接
ESTABLISHED 连接已建立,正在通信 客户端与服务器正常通信
TIME_WAIT 主动关闭方等待2MSL 大量短连接场景,端口被占用
CLOSE_WAIT 被动关闭方等待应用关闭 程序bug,忘记关闭连接
FIN_WAIT1/2 主动关闭方等待确认 正常关闭过程中的中间状态
排查要点:QUIC虽然跑在UDP上,但它的连接状态跟TCP的ESTABLISHED类似。如果你发现QUIC连接异常,不要只看UDP端口状态,还要看QUIC应用层的连接状态。我习惯用ss -ulnp先确认端口是否在监听,然后用QUIC自带的连接管理命令查看内部连接状态。

2.4.2 UDP端口状态

UDP端口的状态就简单多了。它只有两种:

  • UNCONN:端口已绑定,等待接收数据。这是UDP监听端口的正常状态。
  • 未绑定:端口没有被任何进程使用。

UDP没有连接状态,因为UDP本身是无连接的。数据来了就收,收完就完事。但QUIC在UDP之上实现了自己的连接状态机,所以排查QUIC问题时,你需要同时关注UDP端口层和QUIC连接层。

2.5 端口占用的本质

端口占用,说白了就是某个进程已经绑定了这个端口,其他进程不能再绑定同一个端口(除非设置了端口复用选项)。

我遇到过最典型的场景:重启QUIC服务时,旧进程还没完全退出,新进程启动时发现端口被占用,直接报错退出。这时候用ss -ulnp | grep :443一看,发现旧进程还在,等几秒再试就好了。

避坑指南:我曾经在生产环境遇到过一个问题——QUIC服务启动后,端口显示已绑定,但客户端就是连不上。排查了半天,发现是防火墙把UDP 443给拦了。所以端口占用排查,不光要看端口本身,还要看防火墙、iptables、selinux这些外围因素。

2.6 本章知识体系

下面这张图把端口相关的核心概念串起来了,方便你快速回顾。

端口概念知识体系 端口号 (0-65535) 范围划分 协议差异 进程关系 系统端口 注册端口 TCP状态 UDP状态 绑定与释放 0-1023 1024-49151 LISTEN/ESTABLISHED UNCONN ss/lsof/pid 排查QUIC端口占用时,重点关注: 1. UDP端口是否被其他进程占用 2. QUIC连接层状态是否正常

端口概念是排查QUIC问题的地基。地基不稳,后面所有排查手段都是空中楼阁。记住三点:UDP端口独立于TCP、端口绑定的是进程不是服务、UDP端口状态只有UNCONN。把这三点刻在脑子里,后面章节的排查思路才能用得上。