第11章 UDP:用户数据报协议
11.1 引言
UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个 UDP
|
这与面向流字符的协议不同,如 TCP ,应用 程序产生的全体数据与真正发送的单个 IP数 据报可能没有什么联系。
UDP数据报封装成一份 IP 数据报的格式 如图11-1所示。
RFC 768 [Postel 1980] 是UDP的正式规范。
IP数据报
UDP数据报
UDP
首部 首部 UDP数据
20字节 8字节
图11-1 UDP封装
UDP不提供可靠性:它把应用程序传给 IP层的数据发送出去,但是并不保证它们能到达 目的地。由于缺乏可靠性,我们似乎觉得要避免使用 UDP 而使用一种可靠协议如 TCP。我们 在第17章讨论完 TCP后将再回到这个话题,看看什么样的应用程序可以使用 UDP。
应用程序必须关心 IP数据报的长度。如果它超过网络的 MTU(2.8节),那么就要对 IP数 据报进行分片。如果需要,源端到目的端之间的每个网络都要进行分片,并不只是发送端主 机连接第一个网络才这样做(我们在 2.9 节中已定义了路径 MTU的概念)。在 11.5节中,我们 将讨论 IP分片机制。
11.2 UDP首部
UDP首部的各字段如图 11-2所示。
16位源端口号 16位目的端口号
16位UDP长度 16位UDP检验和
8字节
数据(如果有)
图11-2 UDP首部
端口号表示发送进程和接收进程。在图 1-8中,我们画出了 TCP和UDP用目的端口号来分 用来自 IP层的数据的过程。由于 IP层已经把 IP数据报分配给 TCP或UDP(根据 IP首部中协议字 段值),因此 TCP端口号由 TCP来查看,而 UDP端口号由 UDP来查看。 TCP端口号与 UDP端口 号是相互独立的。
尽管相互独立,如果 TCP和UDP同时提供某种知名服务,两个协议通常选择相同 的端口号。这纯粹是为了使用方便,而不是协议本身的要求。
UDP长度字段指的是 UDP首部和 UDP数据的字节长度。该字段的最小值为 8字节(发送一 份 0字节的 UDP数据报是 OK )。这个 UDP长度是有冗余的。 IP数据报长度指的是数据报全长
(图 3-1),因此 UDP数据报长度是全长减去 IP首部的长度(该值在首部长度字段中指定,如图
3-1所示)。
11.3 UDP检验和
UDP检验和覆盖 UDP首部和 UDP数据。回想 IP首部的检验和,它只覆盖 IP的首部 —并不 覆盖IP数据报中的任何数据。
UDP和TCP在首部中都有覆盖它们首部和数据的检验和。 UDP的检验和是可选的,而 TCP
的检验和是必需的。
尽管 U D P 检验和的基本计算方法与我们在 3 . 2 节中描述的 I P 首部检验和计算方法相类似
(16 bit 字的二进制反码和),但是它们之间存在不同的地方。首先, UDP数据报的长度可以为 奇数字节,但是检验和算法是把若干个 16 bit 字相加。解决方法是必要时在最后增加填充字节
0,这只是为了检验和的计算(也就是说,可能增加的填充字节不被传送)。
其次, UDP数据报和 TCP段都包含一个 12字节长的伪首部,它是为了计算检验和而设置 的。伪首部包含 I P 首部一些字段。其目的是让 U D P 两次检查数据是否已经正确到达目的地
(例如, IP没有接受地址不是本主机的数据报,以及 IP没有把应传给另一高层的数据报传给
UDP)。UDP数据报中的伪首部格式如图 11-3所示。
32位源IP地址
32位目的IP地址
UDP伪首部
0 8位协议(17) 16位UDP长度
16位源端口号
16位UDP长度
16位目的端口号
16位UDP检验和
UDP首部
数据
填充字节(0)
图11-3 UDP检验和计算过程中使用的各个字段
在该图中,我们特地举了一个奇数长度的数据报例子,因而在计算检验和时需要加上填 充字节。注意, UDP数据报的长度在检验和计算过程中出现两次。
如果检验和的计算结果为 0,则存入的值为全 1(65535),这在二进制反码计算中是等效 的。如果传送的检验和为 0,说明发送端没有计算检验和。
如果发送端没有计算检验和而接收端检测到检验和有差错,那么 UDP数据报就要被悄悄
地丢弃。不产生任何差错报文(当 IP层检测到 IP首部检验和有差错时也这样做)。
UDP检验和是一个端到端的检验和。它由发送端计算,然后由接收端验证。其目的是为 了发现 UDP首部和数据在发送端到接收端之间发生的任何改动。
尽管 UDP检验和是可选的,但是它们应该总是在用。在 80年代,一些计算机产商在默认 条件下关闭 UDP检验和的功能,以提高使用 UDP协议的 NFS(Network File System )的速度。 在单个局域网中这可能是可以接受的,但是在数据报通过路由器时,通过对链路层数据帧进 行循环冗余检验(如以太网或令牌环数据帧)可以检测到大多数的差错,导致传输失败。不管相信与否,路由器中也存在软件和硬件差错,以致于修改数据报中的数据。如果关闭端到 端的 UDP检验和功能,那么这些差错在 UDP数据报中就不能被检测出来。另外,一些数据链 路层协议(如 SLIP)没有任何形式的数据链路检验和。
Host Requirements RFC声明,UDP检验和选项在默认条件下是打开的。它还声明,如果发送端已经计算了检验和,那么接收端必须检验接收到的检验和(如接收到检验 和不为0)。但是,许多系统没有遵守这一点,只是在出口检验和选项被打开时才验证 接收到的检验和。
11.3.1 tcpdump输出
很难知道某个特定系统是否打开了 UDP检验和选项。应用程序通常不可能得到接收到的 UDP首部中的检验和。为了得到这一点,作者在 tcpdump程序中增加了一个选项,以打印出 接收到的 UDP检验和。如果打印出的值为 0,说明发送端没有计算检验和。
测试网络上三个不同系统的输出如图 11-4所示(参见封面二)。运行我们自编的 sock程序
(附录 C),发送一份包含 9个字节数据的 UDP数据报给标准回显服务器。
图11-4 tcpdump 输出,观察其他主机是否打开UDP检验和选项
从这里可以看出,三个系统中有两个打开了 UDP检验和选项。 还要注意的是,在这个简单例子中,送出的数据报与收到的数据报具有相同的检验和值
(第3和第4行,第5和第6行)。从图11-3可以看出,两个IP地址进行了交换,正如两个端口号一样。 伪首部和 UDP首部中的其他字段都是相同的,就像数据回显一样。这再次表明 UDP检验和(事 实上,TCP/IP协议簇中所有的检验和)是简单的16 bit和。它们检测不出交换两个16 bit的差错。
作者在 14.2节中在 8个域名服务器中各进行了一次 DNS查询。 DNS主要使用 UDP, 结果只有两台服务器打开了UDP检验和选项。
11.3.2 一些统计结果
文献[Mogul 1992]提供了在一个繁忙的 NFS服务器上所发生的不同检验和差错的统计结果,
时间持续了 4 0 天。统计数字结果如图 11 - 5 所 示。
最后一列是每一行的大概总数,因为以 太网和 I P 层还使用其他的协议。例如,不是 所有的以太网数据帧都是 I P数据报,至少以
层 次 以太网
检验和差错数 近似总分组数
太网还要使用 A R P 协议。不是所有的 I P 数据
图11-5 检测到不同检验和差错的分组统计结果
报都是 UDP或TCP数据,因为 ICMP也用IP传送数据。
注意, TCP发生检验和差错的比例与 UDP相比要高得多。这很可能是因为在该系统中的 TCP连接经常是“远程”连接(经过许多路由器和网桥等中间设备),而UDP一般为本地通信。 从最后一行可以看出,不要完全相信数据链路(如以太网,令牌环等)的 CRC检验。应 该始终打开端到端的检验和功能。而且,如果你的数据很有价值,也不要完全相信 U D P或
TCP的检验和,因为这些都只是简单的检验和,不能检测出所有可能发生的差错。
11.4 一个简单的例子
用我们自己编写的 sock程序生成一些可以通过 tcpdump观察的 UDP数据报:
bsdi % sock -v -u -i -n4 svr4 discard
connected on 140.252.13.35.1108 to 140.252.13.34.9bsdi % sock -v -u -i -n4 -w0 svr4 discard
connected