1. UDP 协议基础回顾

各位同学,咱们今天先聊聊 UDP 协议的基础。别急着跳过,我见过太多人把 UDP 当成“无脑发数据”的工具,结果线上出问题了才回头补课。嗯,咱们先把地基打牢。

1.1 UDP 报文结构:轻量到极致

UDP 的报文头,说白了就 8 个字节。我刚开始学网络时,对比 TCP 那动辄 20 字节的头部,第一反应是“这也太省了吧”。

字段 长度(字节) 说明
源端口 2 发送方端口号(可选,可为 0)
目的端口 2 接收方端口号
长度 2 UDP 头部 + 数据的总长度
校验和 2 覆盖头部和数据(可选,IPv4 下可为 0)

核心要点:UDP 头部只有 8 字节,没有序号、确认号、窗口、标志位。它只管把数据扔出去,不保证到达,不保证顺序。

我记得有一次排查丢包问题,抓包发现校验和字段全是 0。当时我还以为是网卡坏了,后来才意识到——有些场景下,发送端为了省那点 CPU 开销,直接把校验和关了。嗯,这其实是个坑,后面章节会细讲。

1.2 无连接特性:发完就跑

UDP 不需要握手,不需要维护连接状态。你想想看,TCP 要三次握手、四次挥手,UDP 呢?直接调用 sendto() 就完事了。

// 发送端伪代码
int sock = socket(AF_INET, SOCK_DGRAM, 0);
sendto(sock, buffer, len, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
// 发完?发完了。不需要等任何确认。

这个特性带来两个直接后果:

  • 延迟极低——没有握手开销,适合实时场景
  • 不可靠——发出去的数据,你根本不知道对方收没收到

我的经验:做音视频传输时,我习惯在应用层自己加一个轻量级的 ACK 机制。别指望 UDP 帮你做任何事,它就是个“快递员”,货扔门口就走。

1.3 MTU 与分片:看不见的坑

最大传输单元(MTU),以太网环境下通常是 1500 字节。你发一个 2000 字节的 UDP 包,会发生什么?

IP 层会帮你分片。但这里有个大坑——只要有一个分片丢了,整个 UDP 包就废了。为什么?因为 UDP 没有重传机制,IP 层也不会帮你重组后重传。

避坑指南:我曾经在项目中发了一个 64KB 的 UDP 包,结果在公网上几乎全丢了。后来把包大小控制在 1400 字节以内(留点余量给 IP 头部),丢包率直接降了一个数量级。

这里有个简单的计算公式:

UDP 数据负载上限 = MTU - IP头部(20) - UDP头部(8)
以太网下:1500 - 20 - 8 = 1472 字节

你想想看,如果你发的包超过 1472 字节,IP 层就要分片。分片越多,丢包概率越大。我个人习惯,UDP 数据负载控制在 1400 字节以内,留点余量给 IP 选项或隧道头部。

1.4 UDP 与 TCP 的核心差异

很多初学者问我:“UDP 这么不可靠,为什么还要用它?”

咱们直接看对比:

维度 UDP TCP
连接 无连接 面向连接
可靠性 不可靠,无重传 可靠,有重传
顺序 不保证 保证
头部开销 8 字节 20 字节起
流量控制 无 有(滑动窗口)
拥塞控制 无 有(慢启动、拥塞避免)
适用场景 实时音视频、DNS、游戏 文件传输、网页、邮件

说白了,TCP 是个“保姆”,帮你把一切都安排好。UDP 是个“甩手掌柜”,你让它干啥它就干啥,干成啥样它不管。

关键认知:UDP 的“不可靠”不是缺陷,是特性。它把可靠性交给了应用层,让你自己决定怎么做。很多高性能场景,恰恰需要这种“裸奔”的自由。

我记得有一次做游戏服务器,用 TCP 做帧同步,结果网络抖动时客户端卡得不行。换成 UDP 后,丢帧就丢帧,客户端直接插值补帧,体验反而更流畅。嗯,这就是选对协议的价值。

1.5 本章知识体系总览

下面这张图,把 UDP 协议的核心知识点串起来了。我建议你保存下来,后面章节会反复用到这些概念。

UDP 协议核心知识体系 UDP 协议 报文结构(8字节) 无连接特性 MTU 与分片 UDP vs TCP 源端口/目的端口 长度/校验和 无需握手/无状态 IP 分片与重组 可靠 vs 不可靠 💡 核心认知 UDP 的“不可靠”不是缺陷,而是将控制权交给应用层 理解这些基础,才能诊断性能瓶颈

这张图把 UDP 的四个核心维度串起来了。报文结构是基础,无连接特性决定了它的行为模式,MTU 分片是性能优化的关键切入点,而和 TCP 的对比能帮你选对协议。

个人建议:学 UDP 不要只盯着协议本身。你要理解它背后的设计哲学——简单、快速、交给上层。后面讲性能瓶颈时,你会发现很多问题都出在“用错了地方”或者“没管好分片”。