TCP/IP协议:UDP

166 阅读5分钟

UDP是一个简单的面向数据报的运输层协议,进程发送的每一条消息都正好是一个UDP数据报。UDP不提供可靠性,它将应用程序交给UDP的数据报发送出去,但并不保证数据等送达目的端,而可靠性可由应用层保证。

UDP首部

截屏2021-06-10 下午11.32.04.png

源端口号目的端口号分别指发送UDP数据报的进程和接收UDP数据报进程; UDP长度指的是UDP首部和UDP数据的长度。IP数据报长度指的是IP数据报全长,因此UDP数据报长度为IP数据包长度减去IP首部长度; 检验和覆盖UDP首部和数据,UDP检验和是可选的,而TCP检验和是必选的。

UDP检验和

UDP检验和覆盖UDP首部和UDP数据,和IP数据报检验和不同的是它增加了一个12字节的伪首部(伪首部包含IP首部的一些字段)。UDP检验和是一个端到端的检验和,它由发送端计算,然后由接收端验证,如果验证不通过则丢弃该数据报,不会产生任何差错报文。

检验和计算原理:在计算一份数据报的检验和,首先把检验和的字段置为0,然后对参与检验和的所有数据的每个16位进行二进制反码求和(整个数据报可看成是由一串16位的字组成),结果存在于检验和字段中。当收到一份IP数据报后,同样对首部中的每个16位进行二进制反码的求和。由于接收方在计算过程中包含了发送方存放在首部中的检验和,因此如果发送过程中没有差错,接收方计算出来的检验和结果应该全部为1。

IP分片

物理层网络一般会限制每次发送数据报帧的最大长度,叫最大传输单元MTU,如以太网MTU为1500字节。而IP层在发送数据报时,会先判断是发往哪一个接口,并查询该接口的MTU,将要发送的IP数据报和该MTU比较,如果大于MTU大小就会将数据报进行分片。分片可以发送在源主机上,也可以发生在中间路由器上。IP数据报被分片后,会在下一站路由就重新组装,重新组装由目的主机的IP层完成。之所以在下一站就重新组装是为了使分片和组装过程对传输层透明,解耦分层结构。

IP分片数据报中有几个IP首部的字段至关重要。其中标识字段是一个IP数据报的标识值,IP数据报的多个分片数据报都是同一个标识。三位标志字段其中一比特用来表示“更多的片”,除了最后一片外其他分片数据报该位都为1,目的IP层接收到该比特的数据报分片后就开始进行重组。片偏移字段用来指示该片偏离原始数据报开始的位置。数据报被分片后,每个片都是独立的IP数据报了,总长度也会改为该片的长度值,它的路由路径和其他片可能也是不同。

前面所说的三位标志字段中有另一个比特是“不分片”位,将这一比特置为1将不对该数据报进行分片,如果数据报经过MTU小于本身长度的接口时则会产生一个ICMP错误(需要进行分片但设置了不可分片比特)。尽管IP数据报分片看起来是透明的,但有一个明显的缺陷,就是如果某一个分片丢失则必须要整个IP数据报都要重传(由于IP数据报没有重传机制,因此需要由更高层来负责)。如果数据报分片是在中间路由器进行的,则源主机无法知道数据报是如何被分片的,因此需要重发整个数据报。

用Traceroute确定路径MTU

我在上一篇文章中traceroute应有描述了traceroute的原理。尽管大多数系统不支持MTU发现功能,但可以通过traceroute的原理,修改一下流程就能用来发现路径MTU。首先发送一个长度与出口MTU长度相同的UDP数据报,并设置“不分片”比特标志位,且UDP端口号同样设置一个不可能的端口号,TTL每发送一个数据报就加1。每次收到“不能分片”的ICMP差错时,就减小UDP的长度。如果ICMP差错报文包含了出口MTU,则下一个数据报长度就用该MTU,否则的话就用下一个MTU值发送(由于MTU值个数时有限的,将所有的MTU值列出一个个从大到小尝试)。直到收到了端口不可达的ICMP差错时,代表数据报已经到达目的地了,过程中用过的最小MTU就是路径MTU了。

ICMP源抑制差错

源抑制差错是处理UDP数据报的速度赶不上接收数据报的速度,在UDP目的端会发送一个源抑制差错给源主机。UDP数据报接收进程会有一个数据报缓存空间,接收到的数据报会先缓存起来,再解析处理UDP数据报,如果缓存已满,且正在处理数据报则会触发错误。