UDP 和 TCP 的区别:对照表、首部长度与端口选型
UDP 和 TCP 都是传输层协议,区别在于可靠性由谁负责:TCP 先握手建立连接,按序号确认、丢了重传、按网络状况调速,首部至少 20 字节;UDP 不建连接、不确认、不调速,首部固定 8 字节,可靠性交给应用自己处理。放行端口、压测和排查丢包时,两者的做法和要看的指标都不一样。
UDP 和 TCP 是 TCP/IP 传输层的两个协议,IP 协议号分别是 17 和 6。TCP(传输控制协议)面向连接:先三次握手,再按序号发送,对方逐段确认,丢了就重传,并且按接收方的处理能力和网络拥塞程度调节速度,交给应用的是一条不丢、不乱、不重的字节流。UDP(用户数据报协议)无连接:应用交给它一个报文,它就发出一个数据报,不确认、不重传、不调速。代价和收益都写在首部里:TCP 首部最少 20 字节,UDP 只有 8 字节。业务用哪个协议通常由开发者决定,运维要做的是弄清每个服务走哪个协议,放行端口、压测、排查丢包时不要用错方法。
TCP 和 UDP 的区别对照表
| 对比项 | TCP | UDP | 对运维的影响 |
|---|---|---|---|
| IP 协议号 | 6 | 17 | 防火墙和 ACL 靠它区分,-p tcp 与 -p udp 是两条规则 |
| 连接 | 三次握手建立,四次挥手关闭 | 没有连接,第一个包就是数据 | TCP 建连多一个往返;UDP 端口没有握手可以用来验证“通不通” |
| 可靠性 | 序号、确认、超时重传,保证不丢、不乱序、不重复 | 不保证,丢失、乱序、重复都原样交给应用 | TCP 丢包表现为变慢;UDP 丢包表现为数据缺失:卡顿、花屏、查询超时 |
| 流量控制 | 接收窗口:接收方来不及处理时让发送方暂停 | 没有,接收缓冲区满了就丢 | UDP 服务要盯接收缓冲区溢出计数 |
| 拥塞控制 | 有,Linux 默认 CUBIC,可选 BBR | 没有,应用发多快就多快 | 多条 TCP 流会自动分享带宽;UDP 洪流会挤占同一出口上的 TCP |
| 数据形式 | 字节流,没有消息边界 | 数据报,发一次对应收一次 | TCP 应用要自己切分消息 |
| 首部长度 | 20–60 字节 | 固定 8 字节 | 小包业务里差别明显,见下一节 |
| 单包载荷(IPv4,MTU 1500) | MSS 1460 字节,带时间戳选项时 1448 | 不分片最多 1472 字节 | UDP 一次发得更大,就会触发 IP 分片 |
| 通信方式 | 只能一对一 | 一对一、广播、组播 | DHCP 靠广播,组播直播只能用 UDP |
| 状态 | 两端都维护连接状态和收发缓冲区 | 协议本身没有状态 | 状态防火墙对 UDP 只能按超时判断“会话”是否结束 |
一句话概括:TCP 把可靠性做在协议里,UDP 把可靠性留给应用。所以 UDP 不是“差一点的 TCP”,而是一个更薄的底座:DNS 在它上面做超时重查,QUIC 在它上面重新实现了一整套可靠传输。
首部长度:TCP 20 字节、UDP 8 字节差在哪
两个首部都以源端口、目的端口开头,差别全在 TCP 多出来的那些字段,每个字段对应一项能力:
| 字段 | TCP | UDP | 用来做什么 |
|---|---|---|---|
| 源端口、目的端口 | 各 16 位 | 各 16 位 | 区分同一台主机上的程序 |
| 序号 | 32 位 | 无 | 给每个字节编号,用来排序和去重 |
| 确认号 | 32 位 | 无 | 告诉对方“这之前的都收到了” |
| 首部长度 | 4 位,单位是 4 字节 | 无;另有 16 位长度字段,含首部和数据 | TCP 首部可变长,靠它找到数据从哪开始,最大 15 × 4 = 60 字节 |
| 标志位 | SYN、ACK、FIN、RST、PSH、URG 等 | 无 | 建立、确认、关闭、复位连接 |
| 窗口 | 16 位 | 无 | 流量控制:本端还能接收多少字节 |
| 校验和 | 16 位,必须计算 | 16 位,IPv4 下可以填 0 | 发现传输差错 |
| 紧急指针 | 16 位 | 无 | 很少使用 |
| 选项 | 0–40 字节 | 无 | MSS、窗口扩大、SACK、时间戳 |
加起来,TCP 固定部分是 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 = 20 字节,UDP 是 2 + 2 + 2 + 2 = 8 字节。
这 12 字节的差距在不同业务里分量完全不同。假设一个游戏每次同步 100 字节的状态:走 UDP,IP 包是 20 + 8 + 100 = 128 字节;走 TCP,Linux 默认带时间戳选项,TCP 首部 32 字节,IP 包是 20 + 32 + 100 = 152 字节,多了约 19%,而且对方还要回 ACK(Linux 会延迟确认、把几个包合并成一次),每个纯 ACK 又是一个 52 字节的 IP 包。传大文件时正好相反:1500 字节的满载包里 TCP 首部只占 2% 左右,首部长短几乎不影响吞吐,起作用的是重传和拥塞控制。
常见服务各走哪个协议
| 服务 | 默认端口 | 协议 | 说明 |
|---|---|---|---|
| SSH、FTP 控制连接、SMTP、HTTP | 22、21、25、80 | 只用 TCP | — |
| BGP | 179 | 只用 TCP | 路由器之间的会话 |
| MySQL、Redis | 3306、6379 | 只用 TCP | — |
| DHCP | 67、68 | 只用 UDP | 客户端还没有地址,只能靠广播 |
| TFTP、NTP、SNMP | 69、123、161 与 162 | UDP | SNMP 规范上也能走 TCP,设备实际基本只用 UDP |
| IPMI(RMCP+) | 623 | 只用 UDP | — |
| VXLAN、WireGuard | 4789、常用 51820 | 只用 UDP | 隧道封装 |
| DNS | 53 | 两种都用 | 查询多走 UDP;应答太大和区域传送走 TCP |
| HTTPS | 443 | 两种都用 | HTTP/1.1、HTTP/2 走 TCP,HTTP/3 走 UDP |
| RDP | 3389 | 两种都用 | TCP 建立会话,较新的客户端和服务器再加一条 UDP 传画面 |
| iperf3 | 5201 | 两种都用 | 控制连接始终走 TCP,UDP 测试的数据走 UDP |
| OpenVPN | 1194 | 二选一 | 默认 UDP,可改为 TCP,以服务端配置的 proto 为准 |
| Syslog | 514 | 二选一 | 传统上用 UDP,rsyslog 等也支持 TCP,端口以配置为准 |
| Minecraft Java 版、基岩版 | 25565、19132 | TCP、UDP | 同一款游戏,两个版本用的协议不同 |
最容易出问题的是“两种都用”的几项。业务方说“开一下 443”,要追问是否启用了 HTTP/3;只放行 TCP 443 时网站照样能打开,只是浏览器退回 HTTP/2,问题不会暴露,但 HTTP/3 的效果也就没有了。“二选一”的服务,以服务端配置文件里写的为准,例如 OpenVPN 看 proto udp 还是 proto tcp。
放行端口时:先确认服务监听的是哪个协议
一个典型工单:客户在服务器上搭了 Minecraft 基岩版,安全组里放行了 19132,玩家还是连不上。查下来是安全组规则选成了 TCP,而基岩版用的是 UDP。这类问题按三步排除:
- 在服务器上看服务实际监听的协议。
ss -tulnp同时列出 TCP 和 UDP,第一列 Netid 就是协议;UDP 没有连接,状态显示为 UNCONN 而不是 LISTEN:
ss -tulnp | grep -E ':(22|19132) '
udp UNCONN 0 0 0.0.0.0:19132 0.0.0.0:* users:(("bedrock_server",pid=2817,fd=9))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))
- 按协议放行,端口号相同也要分开写。 安全组规则和系统防火墙都要带上协议,19132/tcp 放行了,19132/udp 仍然是关着的:
firewall-cmd --permanent --add-port=19132/udp && firewall-cmd --reload # firewalld
ufw allow 19132/udp # ufw
- 验证时别拿 TCP 的办法测 UDP。
nc -zv -w 3 203.0.113.10 22对 TCP 端口有明确结论:成功、被拒绝或超时。换成nc -zuv测 UDP 端口,只要没收到 ICMP 端口不可达,它多半也报告成功,这个结果不能作数;以服务器上tcpdump -nni any udp port 19132能否看到玩家的请求为准。
压测:iperf3 测 TCP 和测 UDP,看的指标不同
同一条链路,用 iperf3 分别测 TCP 和 UDP,回答的是两个不同的问题:
# TCP:一条受拥塞控制的连接(或 -P 指定多条)最多能跑多快
iperf3 -c 203.0.113.10 -t 30 -P 4
# UDP:按指定速率发送,对端收到多少、丢了多少、抖动多大
iperf3 -c 203.0.113.10 -u -b 300M -t 30
TCP 测试遇到丢包会自己降速,结果是一个“被丢包和延迟压低之后的速度”,丢包本身只体现在 Retr(重传段数)一列;UDP 测试不管网络状况,按 -b 指定的速率一直发,结果直接给出丢包比例(Lost/Total Datagrams)和抖动(Jitter)。iperf3 的 UDP 测试默认只发 1 Mbit/s,必须用 -b 指定速率;对端的防火墙要同时放行 TCP 5201 和 UDP 5201。
两种结果合起来看:
| TCP 结果 | UDP 结果(同等速率) | 判断 |
|---|---|---|
| 跑满签约带宽 | 丢包接近 0 | 链路正常 |
| 跑不满,Retr 很多 | 较低速率下就有持续丢包 | 链路本身在丢包(线路、光模块、拥塞),TCP 是被丢包拖慢的 |
| 跑不满,Retr 很少 | 不丢包 | 瓶颈在窗口或延迟,不在丢包;加大并发连接数或调大缓冲区再测 |
| — | 超过某个速率后丢包陡增 | 碰到了限速或端口上限,这个速率就是实际可用带宽 |
| — | 丢包,同时对端 UdpRcvbufErrors 同步增长 |
包丢在接收端主机内部,不是线路问题 |
UDP 压测还有一个注意事项:它不会因为拥塞而让步。在生产出口上跑不设上限的 UDP 测试,会把同一出口上所有 TCP 业务一起挤慢,压测应放在低峰并控制速率和时长。
排查丢包:TCP 看重传,UDP 看接收端计数
同样 1% 的丢包,落在两种协议上的表现不同,查的地方也不同。
TCP:丢包变成重传和降速。 业务表现是慢,而不是数据错。看单条连接用 ss -ti,输出里的 retrans:0/37 表示这条连接累计重传了 37 次,rtt:35.2/1.1 是平滑后的往返时间和它的波动(毫秒);看整机用 nstat -az TcpRetransSegs TcpOutSegs,间隔一段时间取两次差值,重传段数除以发送段数就是重传率。
ss -ti dst 203.0.113.10
UDP:协议层没有重传,丢了就没了。 业务表现是语音断续、画面花屏、DNS 偶发超时。先排除主机自己丢的:
nstat -az UdpInDatagrams UdpInErrors UdpRcvbufErrors UdpNoPorts
| 计数器 | 增长说明 |
|---|---|
| UdpRcvbufErrors | 接收缓冲区满了,程序读得不够快,要调大缓冲区或优化程序 |
| UdpNoPorts | 数据报发到了没有程序监听的端口,内核回了 ICMP 端口不可达;服务没起来或端口配错 |
| UdpInErrors | 接收出错的总数,包含缓冲区溢出和校验和错误 |
主机计数正常,再查路上。这时要注意探测协议要和业务一致:ping 和 mtr 默认用 ICMP,有些网络对 ICMP、UDP 的处理与 TCP 不同,常见于跨境链路和带防护策略的线路,会对某类流量限速或降低转发优先级。用 ICMP 测出来不丢包,不代表 UDP 业务也不丢。mtr 可以直接改用业务协议探测:
mtr -n -r -c 200 -T -P 443 203.0.113.10 # TCP SYN 探测 443 端口
mtr -n -r -c 200 -u -P 53 203.0.113.10 # UDP 探测
读结果时看最后一跳:中间某一跳显示丢包、后面各跳都不丢,通常是那台路由器对探测包的回应做了限速,不是真的丢包。
在机房里怎么落地
两种协议对机房的另一个区别是“会不会让路”。TCP 有拥塞控制,出口紧张时各条连接会自动降速;UDP 没有,一台服务器被利用做反射放大的跳板,或者客户跑起了不限速的 UDP 业务,流量会一直顶在端口上限,挤占同一上联的其他客户。Toplink DCIM 的带宽自动限速取一段时间窗口内的平均带宽做判断,入方向和出方向各有自己的阈值,超标就把交换机端口压到设定的速率,流量回落并保持到设定的时长后自动恢复原速率,对这类不会自己降速的流量很有用。限速、端口开关这些动作由交换机管理按厂商指令集下发到交换机,不用值班人员逐台登录。服务器上开放了哪些 TCP、UDP 端口,仍要在系统防火墙和安全组里按协议逐条收紧。
常见问题
TCP 一定比 UDP 慢吗?
不一定。链路干净时,TCP 同样能跑满带宽,它的“慢”主要体现在建连多一个往返、丢包后要等重传和降速。对延迟敏感、又能容忍少量数据丢失的业务,UDP 的优势才明显。
为什么 VPN 隧道大多用 UDP 承载?
隧道里跑的多半是 TCP 连接,它们自己会重传。外层再用 TCP 的话,一旦丢包,内外两层同时重传、同时降速,吞吐会急剧下降。所以 WireGuard 只用 UDP,OpenVPN 默认也是 UDP,TCP 模式一般只在 UDP 被封锁时备用。
UDP 能做到可靠传输吗?
能,但要由应用自己实现。QUIC 在 UDP 之上实现了确认、重传和拥塞控制,HTTP/3 就跑在它上面;TFTP 每传一块等一次确认;DNS 靠客户端超时重查。