一、UDP协议基础:从报文到实战
聊UDP之前,我先问个问题:你平时写网络程序,是不是下意识就选了TCP?
我早年也这样。总觉得TCP可靠、有保障,UDP嘛…丢包、乱序,听着就不靠谱。直到有一次做实时音视频项目,用TCP推流,延迟高得离谱,用户骂声一片。后来换成UDP,问题迎刃而解。从那以后,我对UDP的看法彻底变了。
说白了,UDP和TCP是两种不同的哲学。TCP追求「完美」,UDP追求「快」。没有谁好谁坏,关键看场景。
1.1 UDP协议栈结构
UDP在协议栈里的位置很简单——传输层。它下面是IP层,上面是应用层。
核心要点:UDP只做两件事——端口复用和差错校验。它不建立连接,不保证可靠,不控制拥塞。
我习惯把UDP协议栈画成四层模型:
- 应用层:你的业务代码,比如DNS查询、视频流推送
- 传输层(UDP):加个UDP头,扔给IP层
- 网络层(IP):加个IP头,找路由
- 链路层:物理传输
嗯,这里要注意:UDP不维护任何状态。你发一个包,它就走一个包。没有握手,没有确认,没有重传。这就是它快的根本原因。
1.2 UDP报文格式
UDP报文头有多简单?就8个字节。我当年第一次看到这个结构,第一反应是:就这?
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 | 16位(2字节) | 发送方端口号,可选(可为0) |
| 目的端口 | 16位(2字节) | 接收方端口号,必填 |
| 长度 | 16位(2字节) | UDP头+数据的总长度,最小8 |
| 校验和 | 16位(2字节) | 可选校验,IPv4下可为0 |
你想想看,TCP光握手就要3个包,UDP连个招呼都不打。这就是为什么UDP适合实时场景——它把「礼貌」省了,直接开干。
实战经验:我在做游戏同步协议时,经常把UDP校验和设为0。为什么?因为游戏场景下,偶尔的比特错误远比重传导致的延迟更可接受。当然,金融交易场景千万别这么干。
1.3 UDP与TCP核心区别
这个对比表我建议你背下来。面试常考,设计系统时也常用。
| 对比维度 | UDP | TCP |
|---|---|---|
| 连接 | 无连接,发就完了 | 面向连接,先握手 |
| 可靠性 | 不保证,丢包就丢了 | 保证,重传直到确认 |
| 顺序 | 不保证,可能乱序 | 保证,按序交付 |
| 速度 | 快,无额外开销 | 慢,有确认和重传 |
| 头部大小 | 8字节 | 20-60字节 |
| 流量控制 | 无 | 有滑动窗口 |
| 拥塞控制 | 无 | 有,慢启动+拥塞避免 |
| 应用场景 | 实时音视频、DNS、游戏 | 网页、文件传输、邮件 |
避坑指南:我曾经在一个物联网项目里,用UDP传输传感器数据。结果丢包率高达15%,数据完全没法用。后来加了应用层ACK和重传机制,才解决问题。记住:UDP不保证可靠,不代表你不能自己实现可靠。
1.4 UDP适用场景分析
什么时候该用UDP?我总结了四个典型场景:
- 实时音视频:视频通话、直播。丢几帧画面,用户感觉不到。但延迟高了,用户直接骂娘。
- DNS查询:一个请求一个响应,用TCP反而浪费。UDP一把梭,快就一个字。
- 在线游戏:尤其是FPS、MOBA类。玩家位置、技能释放,延迟比可靠性重要得多。
- 物联网传感器:大量小数据包,允许偶尔丢失。用TCP反而增加功耗和带宽。
反过来,什么时候别用UDP?
- 文件传输:丢一个字节,整个文件就废了。
- 网页浏览:HTML、CSS、JS必须完整加载。
- 数据库事务:数据一致性是命根子。
我的建议:如果你不确定该用UDP还是TCP,先问自己三个问题:1)能接受丢包吗?2)延迟敏感吗?3)数据量小且频繁吗?三个「是」就选UDP,否则选TCP。