1. UDP协议概述:它在协议栈里的位置、与TCP的核心区别、以及我为什么离不开它

各位好,我是老周。今天咱们开始聊UDP协议。说实话,UDP这玩意儿在很多人眼里就是个“不可靠的传输协议”,甚至有些刚入行的朋友觉得它就是个“阉割版TCP”。嗯,这种看法其实挺片面的。我在做流媒体传输那几年,UDP可是我的主力工具。

先搞清楚一件事:UDP不是设计缺陷,而是设计取舍。它把可靠性交给上层应用,自己只做一件事——把数据从A点扔到B点,越快越好。

1.1 UDP在TCP/IP协议栈中的位置

TCP/IP四层模型,从上到下分别是:应用层、传输层、网络层、网络接口层。UDP和TCP一样,都坐在传输层这个位置上。

关键点:UDP直接封装在IP数据报里,协议号是17。你抓包的时候看到IP头里Protocol字段是17,那就是UDP。

我画了一张图,帮你把UDP在协议栈里的位置看清楚:

UDP在TCP/IP协议栈中的位置 应用层 HTTP · DNS · DHCP · SNMP · RTP · 自定义应用 传输层 TCP(协议号 6) UDP(协议号 17) 网络层 IP(IPv4 / IPv6)· ICMP · ARP 网络接口层 以太网 · WiFi · PPP · 物理介质 UDP直接封装在IP数据报中,不建立连接,不维护状态

你看,UDP和TCP在传输层是平级的。应用程序可以选择用TCP还是UDP,甚至自己实现一套传输协议。我当年做视频会议系统时,就是在UDP之上自己搭了一套可靠传输——因为TCP的拥塞控制太“老实”了,不适合实时场景。

1.2 UDP与TCP的核心区别

说白了,TCP是个“老好人”,UDP是个“急先锋”。TCP要握手、要确认、要重传、要保序;UDP呢?发出去就不管了。

我整理了一张对比表,你一看就明白:

对比维度 TCP UDP
连接方式 面向连接(三次握手) 无连接(直接发)
可靠性 可靠传输(确认+重传) 尽最大努力交付(不保证)
数据顺序 保序(按序交付) 不保序(可能乱序)
流量控制 有(滑动窗口) 无
拥塞控制 有(慢启动、拥塞避免) 无
首部开销 20~60字节 8字节固定
传输模式 字节流 数据报(有边界)
典型场景 网页、文件传输、邮件 DNS、DHCP、视频流、游戏

我的经验:UDP首部只有8字节,TCP最少20字节。别小看这12字节的差距,在高频交易场景下,每微秒都是钱。我曾经优化过一个行情推送系统,从TCP切到UDP后,延迟直接降了40%。

你可能会问:UDP这么“不靠谱”,为什么还要用它?原因很简单——有些场景下,可靠性反而是累赘。

举个例子:你在看视频直播,偶尔丢一帧画面,顶多卡顿一下。但如果用TCP,丢包后它会重传,重传的数据到了也没用了——画面已经过去了。这就是所谓的“迟到比不到更糟糕”。

1.3 UDP的应用场景

UDP的应用场景,说白了就三个字:快、轻、简。我挑几个典型的说说:

1.3.1 DNS(域名解析)

你每次访问网站,浏览器都要先做DNS查询。DNS查询默认用UDP 53端口。为什么?因为查询报文就几十个字节,用TCP建立连接的开销比查询本身还大。你想想看,为了问一句“www.example.com的IP是多少”,先花三个报文握手,是不是太浪费了?

注意:DNS也支持TCP,但只在响应超过512字节(现在通常是1232字节)或区域传输时才会切到TCP。我排查过一个DNS超时问题,最后发现是UDP报文被防火墙截了,客户端等超时后才切TCP——白白浪费了5秒。

1.3.2 DHCP(动态主机配置协议)

你的电脑插上网线就能上网,靠的就是DHCP。DHCP全程用UDP,客户端用68端口,服务器用67端口。为什么不用TCP?因为DHCP在分配IP之前,客户端连自己的IP都没有,TCP的三次握手根本建立不起来。这是个典型的“先有鸡还是先有蛋”的问题。

我记得有一次帮客户排查网络故障,发现DHCP请求发不出去。抓包一看,交换机上配了DHCP Snooping,但信任端口没设对。嗯,这种坑踩过一次就记住了。

1.3.3 视频流与实时通信

这是UDP的主战场。RTP(实时传输协议)就是跑在UDP之上的。视频会议、直播、VoIP,底层全是UDP。我参与过一个在线教育平台,最初用TCP推流,结果网络一波动就卡成PPT。后来换成UDP + FEC(前向纠错),用户体验直接起飞。

为什么会这样?因为视频流对延迟敏感,但对丢包有一定容忍度。丢一个包,画面花一帧,下一帧就恢复了。如果用TCP重传,整个画面都得等,反而更糟。

1.3.4 在线游戏

你玩《王者荣耀》或《绝地求生》时,网络传输用的就是UDP。游戏里你按一下技能,这个操作必须立刻发出去。如果用TCP,万一丢包了要重传,等你技能到了,人早就凉了。游戏引擎通常会在UDP之上做自己的可靠性保障——比如只重传关键操作(如购买装备),非关键操作(如移动)丢了就丢了。

1.3.5 SNMP(简单网络管理协议)

网络设备(交换机、路由器)的监控告警,很多走的是SNMP。SNMP默认用UDP 161/162端口。为什么?因为网络设备CPU资源有限,跑TCP的开销太大。而且监控数据丢了就丢了,下一轮采集马上补上。

避坑指南:我曾经遇到过SNMP告警丢失的问题。排查后发现是UDP接收缓冲区太小,流量一高就丢包。解决方案很简单:调大net.core.rmem_default和net.core.rmem_max。Linux下默认的UDP接收缓冲区只有208KB,高并发场景下根本不够用。

1.4 什么时候该用UDP?

我个人的判断标准很简单,三条:

  1. 能容忍丢包——丢了不影响核心功能,或者应用层自己能处理
  2. 对延迟敏感——宁可丢包也不愿等重传
  3. 报文短小且独立——一次查询一次响应,不需要维持长连接

满足任意两条,UDP就是你的首选。如果三条都满足——那UDP简直是为你量身定做的。