易栈 · 一盏

塞外秋来,衡阳雁去

运输层:UDP、广播、多播

一、UDP:用户数据报协议

UDP提供无连接、不可靠的数据传输。它把应用层传给IP层的数据发出去,但是不保证数据能够到达目的地。

UDP数据报格式如下:

源端口号(2字节)|目的端口号(2字节)|UDP长度(2字节)|UDP校验和(2字节)|数据(可以为0字节)

  • 端口号:前面说过运输层用端口号来识别数据属于哪个应用程序。这里要注意的是TCP端口号和UDP端口号是相互独立的(因为IP层已经根据协议类型字段将数据分发给TCP/UDP,所以即使TCP/UDP包中的端口号相同,也不会发生冲突)。TCP和UDP同时提供某种知名服务时,通常会使用相同的端口号(例如ssh 22/tcp 22/udp),这只是为了使用方便并非受到协议的限制。
  • UDP长度:指UDP首部和UDP数据的字节长度。这个长度是冗余的,因为IP数据报中有足够的信息可以算出数据部分的长度。UDP首部的长度为8个字节(重要!在估算数据报长度时常常会用到)。
  • UDP校验和:覆盖UDP首部和UDP数据的校验和,计算方式与前面介绍过的IP首部校验和的相同。如果接收方检测到校验和有错,会悄悄丢弃UDP数据报,不产生任何差错报文。

使用UDP要特别注意分片问题。TCP会控制每次发包的大小不超过对端通告的最大报文段长度(MSS),所以TCP发的包一般不会被分片。但是UDP则是进程的每个输出操作都产生一个UDP数据报,并组装成IP数据报,如果这个IP数据报长度超出链路层MTU,就会被分片。分片的一大缺点是即使只丢失一片数据也要重传整个数据报。IP层本身没有超时重传的机制,而是由更高层来负责超时和重传。运输层协议中,TCP有超时重传机制,而UDP没有,所以分片会导致UDP丢包概率增加。

使用UDP时可能会遇到的两个ICMP差错:

  • ICMP不可达差错(需要分片):前面讲过ICMP目的不可达差错有几种,其中一种是“需要分片但设置了DF标志”差错。当路由器收到一份需要分片的数据报(长度超过路由器外出接口的MTU),而在该数据报的IP首部又设置了不分片(DF)标志,则会给源主机返回一个ICMP不可达差错。这个差错可以用来检测路径MTU。方法是先发一个设置了不分片标志大长度的分组。如果收到不可达差错,表明该分组的长度超过了路径MTU的大小,于是减小分组长度(有的系统会在差错报文中给出自己的MTU信息。如果差错报文中没有给出,可以估算一个较小的分组长度),再次尝试发送。重复上述步骤直到分组发送成功,这时候使用的分组长度即路径MTU。要制造大长度分组,可以使用UDP(无法强制TCP发大长度分组)。
  • ICMP源站抑制差错:当一个系统(路由器或主机)接收数据报的速度比其处理速度快时(也就是处理不过来了),可能产生这个差错。注意这里说“可能“,因为有的系统会直接丢弃数据报而不返回差错。使用UDP发数据时,由于UDP不会控制发送速度,如果应用程序发数据发得很急,就有可能产生这个差错。

二、广播和多播

我们常见的是单播,即把数据发往单个目的主机。广播是将数据报发送到网络中的所有主机,多播是将数据报发送到网络的一个主机组。

广播和多播仅应用于UDP网络层链路层都有广播和多播地址。网络层广播/多播数据报发到链路层时,会相应地用链路层广播/多播发出去。以太网广播地址为ff:ff:ff:ff:ff:ff,多播地址是所有最高字节最低位为1的MAC地址。IP广播和多播的情况比较复杂,下面将一一介绍。

1、广播

IP广播地址有四种类型:

  • 受限的广播:指向处于同一物理网络中的所有主机。受限广播地址是255.255.255.255。路由器不会转发受限广播的数据报,所以它仅出现在本地网络中。
  • 指向网络的广播:指向同一网络的所有主机。网络广播地址为“网络号+全1主机号”。
  • 指向子网的广播:指向同一子网的所有主机。子网广播地址为“网络号+子网号+全1主机号”。
  • 指向所有子网的广播:已被弃用,建议用多播代替。

2、多播

发往某个IP多播地址的数据,到了链路层会转换成相应的以太网多播地址发出去。

  • IP多播地址:224.0.0.0~239.255.255.255(即D类地址:1110 + 28位多播组号)
  • 以太网多播地址:01:00:5e:00:00:00~01:00:5e:7f:ff:ff(即用低23位来表示多播地址)

注意以太网多播地址的低23位IP多播组号对应,但是IP多播组号有28位,所以每32个IP多播地址映射位一个以太网多播地址(所以链路层无法准确地过滤某个多播组的数据报)。

一个IP多播地址唯一标识一个多播组。加入同一个多播组的主机,都可以接收到发往该多播组地址的数据。一个主机上可能有多个进程,每个进程可以加入不同的多播组。

链路层接收到以太网数据帧时,会检测本机是否属于以太网多播地址对应的多播组,是的话才会把数据发给网络层。也就是链路层会对多播数据报进行过滤,相比之下广播数据报要到UDP层,才会根据端口号被过滤掉。所以广播会增加网络内对广播数据不感兴趣主机的处理负荷

三、实现细节

创建套接字之后,有时候需要给它绑定源IP地址源端口(bind)。多个套接字绑定的IP地址或者端口有冲突时,需要设置以下套接字选项:

  • SO_REUSEADDR:适用于多个套接字绑定的源IP地址不同,源端口相同的情况。有时候主机有多个IP地址(多个接口),设置了这个选项后不同IP地址可以绑定同一个端口。
  • SO_REUSEPORT:适用于多个套接字绑定的源IP地址相同,且源端口相同的情况。只能用于支持多播的系统。

注意这里是针对UDP而言的,对于TCP来说这两个套接字选项有不同的含义。

本文链接:易栈 - 运输层:UDP、广播、多播