网络与 IP

UDP 和 TCP 的区别:对照表、首部长度与端口选型

UDP 和 TCP 都是传输层协议,区别在于可靠性由谁负责:TCP 先握手建立连接,按序号确认、丢了重传、按网络状况调速,首部至少 20 字节;UDP 不建连接、不确认、不调速,首部固定 8 字节,可靠性交给应用自己处理。放行端口、压测和排查丢包时,两者的做法和要看的指标都不一样。

作者 顶联产品团队发布于 7 分钟阅读

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。这类问题按三步排除:

  1. 在服务器上看服务实际监听的协议。 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))
  1. 按协议放行,端口号相同也要分开写。 安全组规则和系统防火墙都要带上协议,19132/tcp 放行了,19132/udp 仍然是关着的:
firewall-cmd --permanent --add-port=19132/udp && firewall-cmd --reload   # firewalld
ufw allow 19132/udp                                                       # ufw
  1. 验证时别拿 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 靠客户端超时重查。

想看看在你的机房里怎么用?

从一次产品演示开始,梳理你的业务链路。

查看价格
服务热线 400-112-2951

让我们聊聊你的 IDC 业务

扫码添加企业微信,预约产品演示或申请试用。

Toplink 企业微信二维码

长按保存或使用企业微信 / 微信扫描

也可致电
400-112-2951
Telegram
@TopLink88