TCP/IP详解07-传输层:UDP--用户数据报协议

TCP/IP详解07-传输层:UDP–用户数据报协议

UDP是一种无连接的,尽最大努力交付的全双工通信的,基于报文段的端到端传输层通信协议。

  • 无连接: UDP在发送数据之前不需要建立连接
  • 尽最大努力交付: UDP不保证可靠交付,主机不需要维持复杂的连接状态
  • 面向报文: UDP是面向报文的。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的的边界,即应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。在接收端,UDP一次交付一个完整的报文。应用程序必须关心 IP 数据报的长度。如果它超过网络的 MTU,那么就要对 IP 数报进行分片。如果需要,源端到目的端之间的每个网络都要进行分片,并不只是发送端主机连接第一个网络才这样做。
  • 其他:
    • UDP没有拥塞控制,网络出现的拥塞不会使源主机的发送速率降低。
    • UDP支持一对一、一对多、多对一和多对多的交互通信。
    • UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

1. UDP首部

TCP/IP详解07-传输层:UDP--用户数据报协议
TCP/IP详解07-传输层:UDP--用户数据报协议

  • 端口号:表示发送进程和接收进程。由于 IP 层已经把 IP 数据报分配给TCP或UDP(根据IP首部中协议字段值),因此 TCP 端口号由 TCP 来查看,而 UDP 端口号由 UDP 来查看。TCP 端口号与 UDP 端口号是相互独立的。
  • UDP长度字段:指的是 UDP 首部和 UDP 数据的字节长度。该字段的最小值为 8 字节(仅有首部)
  • UDP检验和:检测UDP用户数据报在传输中是否有错。有错就丢弃

1.1 UDP检验和

UDP检验和覆盖UDP首部和UDP数据

  • IP首部的检验和,它只覆盖 IP的首部 — 并不覆盖IP数据报中的任何数据。
  • UDP和TCP在首部中都有覆盖它们首部和数据的检验和。UDP的检验和是可选的,而TCP 的检验和是必需的

UDP 检验和的特性

  • 首先,UDP数据报的长度可以为奇数字节,但是检验和算法是把若干个 16 bit字相加。解决方法是必要时在最后增加填充字节 0,这只是为了检验和的计算(也就是说,可能增加的填充字节不被传送)。
  • 其次,UDP数据报和 TCP 段都包含一个 12 字节长的伪首部,它是为了计算检验和而设置的(伪首部既不向下传送也不向上递交,而仅仅是为了计算校验和)。伪首部包含 IP 首部一些字段。其目的是让 UDP 两次检查数据是否已经正确到达目的地

TCP/IP详解07-传输层:UDP--用户数据报协议

注意:

  • 如果发送端没有计算检验和而接收端检测到检验和有差错,那么 U D P数据报就要被悄悄地丢弃。不产生任何差错报文(当 IP层检测到IP首部检验和有差错时也这样做)。
  • UDP检验和是一个端到端的检验和。它由发送端计算,然后由接收端验证。其目的是为了发现UDP首部和数据在发送端到接收端之间发生的任何改动。

例子:

TCP/IP详解07-传输层:UDP--用户数据报协议

在发送方,首先是把全零放入校验和字段并且添加伪首部。然后,把UDP数据报看成是由许多16位的字串连接起来。若UDP数据报的数据部分不是偶数个字节,则要在数据部分末尾增加一个全零字节(但此字节不发送)。接下来就按二进制反码计算出这些16位字的和。将此和的二进制反码写入校验和字段。在接收方,把收到的UDP数据报加上伪首部(如果不为偶数个字节,还需要补上全零字节)后,按二进制反码计算出这些16位字的和。当无差错时其结果应全为1。否则就表明有差错出现,接收方就应该丢弃这个UDP数据报。

1.2 最大UDP数据报长度

理论上,IP 数据报的最大长度是 65535 字节,这是由IP首部 16 比特总长度字段所限制的。去除 20 字节的 IP 首部和 8 个字节的 UDP 首部, UDP 数据报中用户数据的最长长度为 65507 字节。但是,大多数实现所提供的长度比这个最大值小。

  • 第一,应用程序可能会受到其程序接口的限制。socket API提 供了一个可供应用程序调用的函数,以设置接收和发送缓存的长度。对于 UDP socket,这个长度与应用程序可以读写的最大 UDP 数据报的长度直接相关。现在的大部分系统都默认提供了可读写大于 8192 字节的 UDP 数据报(使用这个默认值是因为 8192 是 NFS 读写用户数据数的默认值)。
  • 第二个限制来自于 TCP/IP 的内核实现。可能存在一些实现特性(或差错),使 IP 数据报长度小于65535字节。

2. IP 分片

2.1 原理

IP 在从上层接到数据以后,要根据 IP 地址来判断从哪个接口发送数据(通过选路),并进行 MTU 的查询,如果数据大小超过 MTU 就进行数据分片(分片可以发生在原始发送端主机上,也可以发生在中间路由器上。)。数据的分片是对上层和下层透明,而数据也只是到达目的地还会被重新组装,不过不用担心,IP 层提供了足够的信息进行数据的再组装。

在 IP 头里面,16bit 识别号唯一记录了一个 IP 包的 ID(该值在数据报分片时被复制到每个片中),具有同一个 ID 的IP 片将会被重新组装;而 13 位片偏移则记录了某 IP 片相对整个包的位置;而这两个表示中间的 3bit 标志则标示着该分片后面是否还有新的分片(标志字段用其中一个比特来表示“更多的片”。除了最后一片外,其他每 个组成数据报的片都要把该比特置 1)。这三个标示就组成了 IP 分片的所有信息,接受方就可以利用这些信息对IP数据进行重新组织(就算是后面的分片比前面的分片先到,这些信息也是足够了)。

例子:

在一个以太网上,数据帧的最大长度是 1500 字节(其中 1472 字节留给数据,假定 IP 首部为 20 字节,UDP 首部为8字节)。当传送的 UDP 数据为 1473 字节时,则会进行以下分组:

TCP/IP详解07-传输层:UDP--用户数据报协议

  • 端口号在 UDP 首部,只能在第 1 片中被发现。注意,任何运输层首部只出现在第 1 片数据中。
  • IP 数据报是指 IP 层端到端的传输单元(在分片之前和重新组装之后),分组是指在 IP 层和链路层之间传送的数据单元。一个分组可以是一个完整的 IP 数据报,也可以是 IP 数据报的一个分片。

习题:

  • 题:假定有一个以太网(MTU为1500)和一份 8192 字节的UDP数据报,那么需要分成多少个数据报片,每个数据报片的偏移和长度为多少?
  • 题:继续前一习题,假定这些数据报片要经过一条 MTU 为 552 的 SLIP 链路。必须记住每一个数据报片中的数据(除 IP 首部外)为 8字节的整数倍。 那么又将分成多少个数据报片? 每个数据报片的偏移和长度为多少?
    • 每个 1480 字节的数据报片被分成三小片:两个 528 字节和一个 424字节。小于 532(552-20)的8的最大倍数是528。800 字节的数据报片被分成两小片:一个 528 字节和一个 272 字节。这样,原来 8192 字节的数据报变成了SLIP链路上的17个帧。

2.2 ICMP不可达差错(需要分片)

当路由器收到一份需要分片的数据报,而在 IP 首部又设置了不分片( DF)的标志比特,则会产生生 ICMP 不可达差错。

TCP/IP详解07-传输层:UDP--用户数据报协议

2.3 用Traceroute确定路径MTU

2.4 采用UDP的路径MTU发现

3. UDP和ARP之间的交互作用

这是不常被人注意到的一个细节,这是针对一些系统地实现来说的。当 ARP 缓存还是空的时候。UDP 在被发送之前一定要发送一个 ARP 请求来获得目的主机的MAC 地址,如果这个 UDP 的数据包足够大,大到 IP 层一定要对其进行分片的时候,想象中,该 UDP 数据包的第一个分片会发出一个 ARP 查询请求,所有的分片都会等到这个查询完成以后再发送。事实上是这样吗?

结果是,某些系统会让每一个分片都发送一个 ARP 查询,所有的分片都在等待,但是接收到第一个回应的时候,主机却只发送了最后一个数据片而抛弃了其他,这实在是让人匪夷所思。这样,因为分片的数据不能被及时组装,接收主机将会在一段时间内将永远无法组装的 IP 数据包抛弃,并且发送组装超时的 ICMP 报文(其实很多系统不产生这个差错),以保证接收主机自己的接收端缓存不被那些永远得不到组装的分片充满。

4. ICMP源站抑制差错

当一个系统(路由器或主机)接收数据报的速度比其处理速度快时,可能产生这个差错。注意限定词“可能”。 即使一个系统已经没有缓存并丢弃数据报,也不要求它一定要发送源站抑制报文。

5. UDP服务器的设计

UDP协议的某些特性将会影响我们的服务器程序设计,大致总结如下:

  1. 客户IP地址及端口号:来自客户的是 UDP 数据报。IP 首部包含源端和目的端 IP 地址,UDP 首部包含了源端和目的端的 UDP 端口号。当一个应用程序接收到 UDP 数据报时,操作系统必须告诉它是谁发送了这份消息,即源IP地址和端口号。
  2. 目的IP地址:服务器必须要有过滤广播地址的能力。
  3. UDP输入队列:通常服务器系统的每一个端口号都会和一块输入缓冲区对应,进来的输入根据先来后到的原则等待服务器的处理,所以难免会出现缓冲区溢出的问题,这种情况下,UDP数据包可能会被丢弃,而应用服务器程序本身并不知道这个问题。
  4. 限制本地IP地址:服务器应该限制本地IP地址,就是说它应该可以把自己绑定到某一个网络接口的某一个端口上。
    • 大多数 UDP 服务器在创建 UDP 端点时都使其本地 IP 地址具有通配符 ( wildcard )的特点。这就表明进入的 UDP 数据报如果其目的地为服务器端口,那么在任何本地接口均可接收到它。
    • 当服务器创建端点时,它可以把其中一个主机本地 IP 地址包括广播地址指定为端点的本地 IP 地址。只有当目的 IP 地址与指定的地址相匹配时,进入的 UDP 数据报才能被送到这个端点。
  5. 限制远端IP地址
    TCP/IP详解07-传输层:UDP--用户数据报协议
  6. 每个端口有多个接收者当 UDP 数据报到达的目的 IP 地址为广播地址或多播地址,而且在目的 IP 地址和端口号处有多个端点时,就向每个端点传送一份数据报的复制(端点的本地 IP 地址可以含有星号,它可匹配任何目的 IP 地址)。但是,如果 UDP 数据报到达的是一个单播地址,那么只向其中一个端点传送一份数据报的复制。选择哪个端点传送数据取决于各个不同的系统实现。