互联网协议 — IPv4 — 分片与重组
Posted 范桂飓
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了互联网协议 — IPv4 — 分片与重组相关的知识,希望对你有一定的参考价值。
目录
MTU
每种数据链路的 MTU(最大传输单元)都可能不同,不同数据链路(设备)之间传输数据前,需要先确定一个 IP 数据包的大小上限,即 MTU(Maximum transmission unit,最大传输单元),MTU 是 IP 数据包能够传输的数据上限。MTU 的值不是越大越好,更大的 MTU 意味着更低的额外开销,更小的 MTU 意味着更低的网络延迟。
IP 分片与重组
IP 层通过分片来屏蔽数据链路层的差异,实现在不同数据链路上互通。从 IP 的上一层看,它完全可以忽略各个数据链路上的 MTU,只需要按照源 IP 地址发送的长度接收数据包。
当遇到 IP 数据包大于数据链路 MTU 时,往往无法直接发送出去,主机或路由器就会对 IP 数据包进行分片处理。经过分片后的 IP 数据,只会在目标主机上进行重组,中途经过路由器时不会进行重组。
简而言之,IP 分片是因为物理设备的限制,一次能够传输的数据由路径上 MTU 最小的设备决定,一旦 IP 协议传输的数据包超过 MTU 的限制就会发生丢包,所以需要通过 Path MTU Discovery(路径 MTU 发现)功能来获取传输 E2E 路径上的 MTU 限制;
Path MTU Discovery(路径 MTU 发现)
IP 分片机制有两点不足:
- 加重了路由器的处理性能;
- 在分片传输中,一旦某个分片丢失,会造成整个 IP 数据包作废。
为了解决这个问题,就要避免 IP 数据包在中途的路由器上被分片处理。PMTUD(Path MTU Discovery,路径最大传输单元发现)技术,就是用于 “预见” E2E 传输路径间的最小 MTU,继而在主机发送时就完成了分片,而不需要网络中间件来完成分片。
如下图所示,Path MTU 由 MTU 最小的红色物理设备决定,即 1000:
它的工作原理如下:
-
源主机向目的主机发送 IP Header 中 DF(Don’t Fragment,不分片)控制位为 1 的数据包。
-
路径上的网络设备根据 IP 数据包的大小和自身的 MTU 做出不同的决定:
- 如果 IP 数据包大于设备的 MTU,就丢弃数据包并返回一个包含了该设备 MTU 的 ICMP 消息;
- 如果 IP 数据包小于设备的 MTU,就继续向目的主机传递数据包;
- 源主机收到 ICMP 消息后,会不断使用新的 MTU 发送 IP 数据包,直到 IP 数据包达到目的主机为止。
Path MTU 值至少可以缓存约 10 分钟,在这 10 分钟内使用刚得到的 MTU 值,过了 10 分钟后就重新做一次路径 MTU 发现。
上面的例子是 UDP ,如果是在 TCP 的情况下,根据路径 MTU 的大小计算出最大段长度(MSS),然后再根据这些信息进行数据包的发送。因此,在 TCP 中如果使用路径 MTU 发现, IP 层则不会再分片。
TCP 数据段的分片
TCP 协议是面向字节流的协议,应用层交给 TCP 协议的数据并不会以消息为单位向目的主机发送,应用层交给 TCP 协议发送的数据可能会被拆分到多个数据段中。
TCP 协议引入了 MSS(Maximum segment size,最大分段大小)这一概念,它是 TCP 数据段能够携带的数据上限。在正常情况下,TCP 连接的 MSS 是 MTU - 40 字节,即:1460 字节;不过如果通信双方没有指定 MSS 的话,在默认情况下 MSS 的大小是 536 字节。
IP 协议的 MTU 是物理设备上的限制,它限制了路径能够发送数据包的上限,而 TCP 协议的 MSS 是操作系统内核层面的限制,通信双方会在三次握手时确定这次连接的 MSS。一旦确定了 MSS,TCP 协议就会对应用层交给 TCP 协议发送的数据进行拆分,构成多个数据段。
需要注意的是,IP 协议和 TCP 协议虽然都会对数据进行拆分,但是 IP 协议以数据包(Package)为单位组织数据,而 TCP 协议以数据段(Segment)为单位组织数据。
如下图所示,如果 TCP 连接的 MSS 是 1460 字节,应用层想要通过 TCP 协议传输 2000 字节的数据,那么 TCP 协议会根据 MSS 将 2000 字节的数据拆分到两个数据段中:
- 20 字节 IP 头 + 20 字节 TCP 头 + 1460 字节数据;
- 20 字节 IP 头 + 20 字节 TCP 头 + 540 字节数据;
从应用层的角度来看,两个数据段中 2000 字节的数据构成了发送方想要发送的消息,但是 TCP 协议是面向字节流的,向协议写入的数据会以流的形式传递到对端。
TCP 协议为了保证可靠性,会通过 IP 协议的 MTU 计算出 MSS 并根据 MSS 分段避免 IP 协议对数据包进行分片。因为 IP 协议对数据包的分片对上层是透明的,如果协议不根据 MTU 做一些限制,那么 IP 协议的分片会导致部分数据包失去传输层协议头,一旦数据包发生丢失就只能丢弃全部数据。
我们可以通过一个例子分析 MSS 存在的必要性。如下图所示,假设 TCP 协议中不存在 MSS 的概念,因为每个数据段的大小没有上限,当 TCP 协议交给 IP 层发送两个 1600 字节(包括 IP 和 TCP 协议头)的数据包时,由于物理设备的限制,IP 协议的路径 MTU 为 1500 字节,所以 IP 协议会对数据包分片:
四个数据包中只有两个会包含 TCP 协议头,即控制位、序列号等信息,剩下的两个数据包中不包含任何信息。因为网络无法保证数据包的送达顺序,所以当上述四个数据包乱序到达目的主机时,因为数据包中 TCP 协议头的缺失,所以接收方没有办法对数据包进行重组,自然也就无法保证可靠性和顺序了。
可见,TCP 协议拆分数据是为了保证传输的可靠性和顺序,作为可靠的传输协议,为了保证数据的传输顺序,它需要为每一个数据段增加包含序列号的 TCP 协议头,如果数据段大小超过了 IP 协议的 MTU 限制,接收方就无法按顺序对数据包进行重组,TCP 协议也就无法提供可靠性和顺序的保证;
UDP 数据段的分片
IP 协议数据分片对传输层协议是透明的,假设我们使用 UDP 协议传输 2000 字节的数据,加上 UDP 8 字节的协议头,IP 协议需要传输 2008 字节的数据。
如下图所示,当 IP 协议发现待传输的数据大于 1480 字节,就会将数据分成下面的两个数据包:
- 20 字节 IP 协议头 + 8 字节 UDP 协议头 + 1472 字节数据;
- 20 字节 IP 协议头 + 528 字节数据;
数据的接收方在收到数据包时会对分片的数据进行重组,不过因为第二个数据包中不包含 UDP 协议的相关信息,一旦发生丢包,整个 UDP 数据报就无法重新拼装。如果 UDP 数据报需要传输的数据过多,那么 IP 协议就会大量分片,增加了不稳定性。
所以,UDP 协议的数据报不应该超过 MTU - 28 字节,一旦超过该限制,IP 协议的分片机制会增加 UDP 数据报无法重组的可能性。
以上是关于互联网协议 — IPv4 — 分片与重组的主要内容,如果未能解决你的问题,请参考以下文章