网络知识大全
RFC 精读 · Transport · STD 6

RFC 768

User Datagram Protocol —— 整份规范只有三页。先读完它,再去看 TCP,才知道“最小传输层”到底省掉了什么。

编号 / 标题
RFC 768 · User Datagram Protocol
发布
August 1980 · J. Postel
状态
Internet Standard · STD 6
关系
Updated by RFC 9868(UDP Options)
原文
rfc-editor HTML · 纯文本 · datatracker
实验室样本
DNS 查询 / 应答的传输层外壳
Introduction

它保证什么、不保证什么

This protocol  provides  a procedure  for application  programs  to send
messages  to other programs  with a minimum  of protocol mechanism.  The
protocol  is transaction oriented, and delivery and duplicate protection
are not guaranteed.  Applications requiring ordered reliable delivery of
streams of data should use the Transmission Control Protocol (TCP) [2].

注解

UDP 的设计目标是最少机制:给应用一个“把一块数据交给对端端口”的手续,而不是一条可靠管道。原文连着否掉三件事:送达、重复抑制、(对 TCP 而言的)有序字节流。

易误解:“UDP 一定比 TCP 快”。规范没这么说。它只是把可靠性、排序、拥塞控制都推给应用。DNS、DHCP、QUIC、实时音视频用 UDP,是因为它们想自己决定重试与边界,不是因为 8 字节首部有魔力。

Format

用户数据报首部

                  0      7 8     15 16    23 24    31  
                 +--------+--------+--------+--------+ 
                 |     Source      |   Destination   | 
                 |      Port       |      Port       | 
                 +--------+--------+--------+--------+ 
                 |                 |                 | 
                 |     Length      |    Checksum     | 
                 +--------+--------+--------+--------+ 
                 |                                     
                 |          data octets ...            
                 +---------------- ...                 

                      User Datagram Header Format

注解

固定 8 字节:源端口、目的端口、长度、校验和,各 16 bit。没有序号、没有标志位、没有窗口。数据报边界被保留——接收方一次 recv 对应一个 UDP 数据报,不会像 TCP 那样粘成字节流。

易误解:把 UDP 画成“TCP 去掉可靠字段”。更准确的说法是:UDP 只做复用(端口)和可选完整性(校验和)。

Fields

端口、长度

Source Port is an optional field, when meaningful, it indicates the port
of the sending  process,  and may be assumed  to be the port  to which a
reply should  be addressed  in the absence of any other information.  If
not used, a value of zero is inserted.

[……节选页眉,下接 Destination Port / Length]

Destination  Port has a meaning  within  the  context  of  a  particular
internet destination address.

Length  is the length  in octets  of this user datagram  including  this
header  and the data.   (This  means  the minimum value of the length is
eight.)

注解

源端口可以为 0:单向通知、不需要回复时合法。目的端口必须结合目的 IP 才有意义——同样是 53,落到不同主机是不同的 DNS 服务。

Length = 首部 + 数据,最小 8。它和 IP Total Length 不是同一个数:IP 总长还包含 20 字节 IPv4 首部。抓包时若 UDP Length 对不上剩余字节,先怀疑截断或分片。

Checksum

伪首部与“全 0 / 全 1”

Checksum is the 16-bit one's complement of the one's complement sum of a
pseudo header of information from the IP header, the UDP header, and the
data,  padded  with zero octets  at the end (if  necessary)  to  make  a
multiple of two octets.

The pseudo  header  conceptually prefixed to the UDP header contains the
source  address,  the destination  address,  the protocol,  and the  UDP
length.   This information gives protection against misrouted datagrams.
This checksum procedure is the same as is used in TCP.

                  0      7 8     15 16    23 24    31 
                 +--------+--------+--------+--------+
                 |          source address           |
                 +--------+--------+--------+--------+
                 |        destination address        |
                 +--------+--------+--------+--------+
                 |  zero  |protocol|   UDP length    |
                 +--------+--------+--------+--------+

If the computed  checksum  is zero,  it is transmitted  as all ones (the
equivalent  in one's complement  arithmetic).   An all zero  transmitted
checksum  value means that the transmitter  generated  no checksum  (for
debugging or for higher level protocols that don't care).

注解

校验和覆盖 UDP 首部 + 数据 + 一份不算在线上长度里的伪首部(源/目的 IP、协议号 17、UDP 长度)。目的:即使交换机/路由器把包送到错误主机,对端也能发现“这不是给我的”。

两个容易考的特例:计算值为 0 时改发 0xFFFF(全 1);发出去是全 0 表示没算校验和。这是 IPv4 的规则。IPv6 上 UDP 校验和原则上必须使用(另有极少例外),不能再靠“填 0 关掉”。

文末写 protocol number 17。IP 首部 Protocol 字段看到 17,才把数据交给 UDP。

抓包对照

Wireshark 里一条 DNS 查询通常显示为 Ethernet / IPv4 / UDP / DNS。展开 UDP,四个字段全部是线上真实字节,没有“虚拟字段”。

udp.srcport == 53122 udp.dstport == 53 udp.length == 8 + DNS报文 udp.checksum == 0x…. (IPv4 偶尔为 0) tcpdump: udp port 53 udp[0:2] 源端口 udp[2:2] 目的端口 udp[4:2] Length udp[6:2] Checksum

考点与易错点

  1. UDP 首部固定 8 字节;Length 含首部,最小为 8。
  2. 不保证送达、不排序、不去重、无拥塞控制;应用自己决定要不要重试。
  3. IPv4 校验和可为 0(关闭);计算为 0 时发送 0xFFFF。IPv6 不能随意关闭。
  4. 校验和算法与 TCP 相同,都加伪首部,防的是“送到错主机还当自己的”。
  5. 源端口可为 0;目的端口必须放在目的 IP 的语境里理解。
  6. IP Protocol = 17。不要和 TCP 的 6、ICMP 的 1 记混。