Skip to content

IP 分片与重装

2026 大纲 四(三)1 IPv4 分组。与《IPv4 数据报格式》同属一条:首部各字段的位宽与首部校验和算法在那一篇,分片的全部计算集中在本篇

一、IP 没抹平的那件事,在这里补上

网络层用统一的地址和统一的分组格式把异构链路缝成了一张网,但有一件事它没统一:每种数据链路层协议都规定了帧的数据字段最大长度 MTU(以太网是 1500)。一个 IP 数据报的总长度一旦超过下一跳链路的 MTU,链路层就装不下了。

补这个缺口的机制就是分片:把过长的数据报拆成若干个各自带完整 IP 首部的小数据报,各自封装、各自传送,到终点再拼回去。

首部里有三个字段专为这件事而设,加一个被动跟着变的:

  • 标识:原样复制到每一片,是终点"认亲"的唯一凭据;
  • DF:原样复制。DF=1 且超长则直接丢弃并回一个 ICMP 差错报文;
  • MF:本片后面还有片则为 1,是最后一片则为 0;
  • 片偏移:该片数据在原始数据报数据部分中的起始位置 ÷ 8。

被动改变的是总长度——每片各自算各自的。

交互可视化

加载可视化中...

二、分片在路由器,重装只在目的主机

这张图要读出的是不对称:分片可能在路径上发生多次(任何一台出口 MTU 不够的路由器都会做,也包括源主机自己),重装只发生一次、且只在最右端。三条理由:

  1. 路由器不知道后面还有没有更小的 MTU。 拆开之后下一跳可能还得再拆,"先装回去再看要不要拆"是纯粹的白功。
  2. 分片可能走不同的路径。 IP 是无连接的,同一个原始数据报的几个分片完全可能从不同接口出去,中间某台路由器根本凑不齐
  3. 重装要占状态。 缓存已到分片、等剩下的、还要设超时——让处在转发热路径上的路由器为每条正在重装的数据报维持状态,代价高得离谱;而目的主机反正要缓存。

三、片偏移为什么以 8 字节为单位

片偏移只有 13 位,而它要指向的位置落在一个最长 65535 字节的数据报里:

  • 单位取 1 字节:最大偏移 2131=8191 字节,一个 60000 字节的数据报后半截根本没法表示——不可用
  • 单位取 8 字节:最大偏移 8191×8=65528 字节,够覆盖整个数据部分(最多 6553520=65515 字节)。

放大单位是有代价的:片偏移只能是 8 的倍数,于是每一片携带的数据量必须是 8 的整数倍——否则下一片的起点落不到一个能被表示出来的刻度上。这正是下一节计算第一步要向下取整的来源。

"最后一片除外"的例外从哪来:最后一片后面没有下一片了,不需要再给谁提供起始刻度,所以它的数据长度可以是任意值。这不是特批,是"约束本来就只作用于'后面还有片'的情形"的自然结果。

四、计算三步与逐片填字段

设原始数据报总长度 L、首部长度 H(通常 20)、出口链路 MTU 为 M,数据部分 D=LH

第一步,每片能装多少数据d=(MH)/8×8第二步,要分几片n=D/d第三步,逐片填表。

第一步的向下取整千万别跳。 MTU = 1500 时 150020=1480 恰好被 8 整除,这一步会"隐身",做惯了 1500 的题很容易以为它不存在;一旦 MTU 是 576、800、1006 这类数,不取整就全盘错掉。

逐片各字段的值:

字段k 片(k 从 0 起)的值
标识与原始数据报相同
DF与原始数据报相同(通常 0)
MFk<n1 则为 1;若 k=n1继承原始数据报的 MF
片偏移原始片偏移 + k×d/8
数据长度n1 片都是 d;最后一片是 D(n1)d
总长度该片数据长度 + H

⚠️ 表里两处写的是"继承 / 加上原始值"而不是"置 0"。对第一次分片来说原始 MF=0、原始片偏移=0,两者退化成"最后一片 MF=0、第一片偏移 0";二次分片时这两条必须按原样用——片偏移永远相对最原始那个数据报的数据部分起点度量,子片偏移要在原值上累加;而 MF=0 只属于整个原始数据报的最后一片,被拆的那片若 MF=1,它的所有子片 MF 都是 1。这是本篇最容易翻车的地方。

还有两处措辞要分清。最后一片的总长度不等于 MTU——它装多少由余数决定,跟 MTU 没关系;凡是把最后一片也写成"MTU 那么长",一定是错的。片偏移的字段值与字节偏移差 8 倍——问"片偏移字段的值"答 69,问"该片数据从原数据报第几字节开始"答 552。

一次分片与二次分片的完整逐片走查,含三重验算(第一次学、或想把片偏移的累加与 MF 的继承亲手过一遍时展开)

(一)一次分片,MTU 不是 8 的倍数。 一个总长度 3200 字节(固定首部 20 字节)的数据报,要经过一条 MTU = 576 的链路。

第 1 步:算每片可装数据量。 先扣掉每片自己要带的 20 字节首部,再向下取整到 8 的倍数:

d=576208×8=5568×8=69×8=552

556÷8=69.5 不是整数——这正是本例与"MTU=1500"那种情形的区别。若直接用 556,第 2 片的字节起点是 556,556 ÷ 8 = 69.5,片偏移字段填不进去。

第 2 步:算片数。 分片切的是数据部分

D=320020=3180,n=3180552=5.76=6

第 3 步:逐片填表。 片偏移是累加的——每多走一片,起点前进 d 字节,即 d/8=69 个刻度。

分片数据量总长度标识DFMF片偏移(字段值)数据在原报文中的字节区间
1552572与原报文相同0100 ~ 551
2552572同上0169552 ~ 1103
3552572同上011381104 ~ 1655
4552572同上012071656 ~ 2207
5552572同上012762208 ~ 2759
6420440同上003452760 ~ 3179

第 4 步:三重验算(三条互相独立,任一条不过就说明前面算错了):数据总量 552×5+420=3180 ✓;各片总长度都 576,最大 572 ✓;末片自洽 345×8+420=3180 ✓。

注意第 6 片的总长度是 440 而不是 576

(二)二次分片。 上面的第 2 片在后续路径上又遇到 MTU = 316 的链路。它本身是一个完整合法的 IP 数据报:总长度 572、数据 552、MF = 1、片偏移 = 69。二次分片就是拿这个数据报重跑一遍流程,只是初值不再是 0。

d=316208×8=37×8=296,n=552296=2

数据分成 296 + 256。片偏移在原有基础上累加:子片 1 偏移 = 69+0=69;子片 2 偏移 = 69+296/8=106

MF 怎么置:MF 的含义是"我后面还有没有别的片"。第 2 片后面还有第 3~6 片,所以两个子片后面都还有东西——MF 都是 1。

子片数据量总长度标识MF片偏移
2-1296316与原报文相同169
2-2256276同上1106

验算:296+256=552 ✓;两个总长度都 316 ✓。

本例的全部价值在 MF 这一步。 习惯性地把"最后一个子片"的 MF 写成 0,目的主机就会以为整个数据报到第 1103 字节结束,剩下的 2076 字节全部丢失。作为对照:若被二次分片的是第 6 片(它的 MF 本来就是 0),那么它的最后一个子片 MF 才是 0。

(三)字段演变全景。

阶段报文总长度标识DFMF片偏移
原始完整数据报3200X000
一次分片后片 1572X010
片 2572X0169
片 3572X01138
片 4572X01207
片 5572X01276
片 6440X00345
片 2 再分片后片 2-1316X0169
片 2-2276X01106

三条读法:标识列一路不变(重装时唯一的认亲凭据);MF 全程有且只有最后那一片是 0片偏移只增不减且严格递增,因为它永远相对原始数据报起点度量。

五、重装:目的主机凭什么知道"该收多少"

重装的流程是:按标识(配合源 IP、目的 IP、协议)把分片归拢 → 按片偏移把每片放到缓存的第 ×8 字节处 → 判断 0 到 D1 的字节是否被全覆盖。

问题在于 D 从哪来——目的主机一开始并不知道原始数据报有多长。它是靠 MF=0 的那一片反推出来的:

D=×8+

所以最后一片如果丢了,接收方连"该收多少"都不知道,只能一直等到超时。

收不齐怎么办:终点在规定时间内收不到全部分片,就把已收到的分片全部丢弃,并向源点发 ICMP 时间超过报文。IP 层不重传——重传由上层的 TCP 负责。

这一条直接引出分片的三笔代价:① 每片都要多带一个首部;② 丢一片等于丢整个数据报,已收到的全部作废、上层要重传整个原始报文;③ 重装占目的主机的缓存与定时器。所以现代网络的策略是"尽量别分片",不是"分好片"

具体怎么做到不分片,是把 DF 反过来用:源主机故意置 DF=1、从大到小试探,靠收到的 ICMP 差错报文收敛出这条路径上的最小 MTU(路径 MTU),之后全程不再分片。IPv6 干脆禁止路由器分片,把这套试探变成唯一的机制。

本节小结

  1. 13 位的片偏移覆盖不了 65535 字节的空间,只能把单位放大到 8 字节;代价是"每片数据必须凑成 8 的倍数",而"最后一片除外"是因为约束本来只作用于"后面还有片"的情形。计算三步为 d=(MH)/8×8n=(LH)/d → 逐片填表,第一步的向下取整在 MTU=1500 时会"隐身",别养成跳步的习惯。
  2. 片偏移永远相对原始数据报的数据部分起点度量,所以二次分片要在原有偏移上累加;MF=0 只属于整个原始数据报的最后一片,被拆的中间片其所有子片 MF 都是 1。这两条是二次分片的全部难点。
  3. 重装只在目的主机(路由器凑不齐、不该占状态、下游可能还要再拆),靠 MF=0 那一片反推原始数据长度再判全覆盖;收不齐就超时丢弃全部分片并发 ICMP 超时报文,IP 层不重传。DF=1 超长只能丢弃,这条限制被反用成路径 MTU 探测。

考点速记

分片在真题里被考过的形式有两种,都不考二次分片,都卡在同一处:第一步的向下取整

① 第 2 个分片的总长度和 MF 是多少(cn-2021-36)。路由器向 MTU = 800 B 的链路转发一个总长度 1580 B(首部 20 B)的数据报,每个分片尽可能大。

按三步走:d=(80020)/8×8=97.5×8=776D=158020=1560n=1560/776=2.01=3 片,数据量分别是 776、776、8。第 2 片是中间片,总长度 =776+20=796,MF =1,答 B

四个选项正好是两个坑的笛卡儿积:写 800 的是没扣首部(以为 MTU 就是数据量)或没向下取整780 不是 8 的倍数);写 MF=0 的是误以为一共只有 2 片、把第 2 片当成了最后一片。1560/776=2.01 这个"刚过 2 一点点"的设计非常刻意——第 3 片只装 8 个字节,粗略估算很容易漏掉它。

② 最大分片装多少、要分几片、片偏移各是多少(cn-2018-47 的第 (2) 问,整题 7 分)。主机 192.168.1.1 向 192.168.1.208 发一个总长度 1500 B、首部 20 B 的分组,路由器在 MTU = 800 B 的接口上分片,尽可能分为最大片。

同一套动作:d=780/8×8=97×8=776 B(这就是"一个最大 IP 分片封装数据的字节数");D=1480n=1480/776=2 片;片偏移字段值分别是 0776/8=97。第 2 片数据量 1480776=704,不是 8 的倍数也合法——它是最后一片

这一问三个数各有一个坑:776 的坑是取整;2 片的坑是拿总长度 1500 而不是数据 1480 去除;片偏移的坑是答成字节数 776 而不是字段值 97

这道题的第 (1) 问考的是子网划分与广播地址,讲在 IP 编址与子网划分

本篇练习区里还会出现另外九道题,考的是 IP 编址、子网划分与首部字段:cn-2010-37、cn-2011-38、cn-2017-38、cn-2019-37、cn-2022-35、cn-2023-39 讲在 IP 编址与子网划分;cn-2011-47 与 cn-2017-36 讲在 IPv4 数据报格式;cn-2023-40 讲在 IPv6 基础

易错第一步必须向下取整到 8 的倍数。 MTU=1500 时这一步会隐身,换成 800、576 就会翻车。

易错分的是数据部分,不是总长度。 片数用 (LH)/d 算,不是 L/d

易错片偏移字段的值 = 字节偏移 ÷ 8。 问"字段的值"答 97,问"从第几字节开始"答 776。

易错最后一片的总长度由余数决定,与 MTU 无关,而且它的数据量不必是 8 的倍数。

易错每片都要自带一个完整首部,所以每片能装的数据是 MH 再取整,不是 M

易错二次分片时片偏移要在原值上累加,MF 要继承。 中间片的所有子片 MF 都是 1。

易错重装只在目的主机做,路由器不重装;收不齐就超时丢弃全部分片,IP 层不重传。

教材出处
  • 谢希仁《计算机网络》(第 8 版):MTU 与分片的起因,见印刷版 p137(4.2.5 IP 数据报的格式)——"下面的每一种数据链路层协议都规定了一个数据帧中的数据字段的最大长度,这称为最大传送单元 MTU……当一个 IP 数据报封装成链路层的帧时,此数据报的总长度(即首部加上数据部分)一定不能超过下面的数据链路层所规定的 MTU 值……若所传送的数据报长度超过数据链路层的 MTU 值,就必须把过长的数据报进行分片处理";同页给出片偏移的定义:"片偏移指出:较长的分组在分片后,某片在原分组中的相对位置……片偏移以 8 个字节为偏移单位。这就是说,除最后一个数据报片外,其他每个分片的长度一定是 8 字节(64 位)的整数倍";标志字段"MF=1 即表示后面'还有分片'的数据报。MF=0 表示这已是若干数据报片中的最后一个"。
  • 同书 p137–p138【例 4-1】及表 4-5:总长度 3820、数据 3800、限长 1420 的数据报分为 3 片,数据部分 1400/1400/1000,片偏移 0/175/350,MF 为 1/1/0;同页还给出二次分片的结果——数据报片 2 再分为携带 800 与 600 字节的两片时,"这两个数据报片的总长度、标识、MF、DF 和片偏移分别为:820, 12345, 1, 0, 175;620, 12345, 1, 0, 275"。本篇折叠块里"子片 MF 仍为 1、片偏移在原值上累加"两条即由此而来(本篇算例数据为自造,与教材例题不同)。
  • 同书 p137:标识字段"当数据报由于长度超过网络的 MTU 而必须分片时,这个标识字段的值就被复制到所有的数据报片的标识字段中。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报"。
  • 同书 p147(4.4.1 ICMP 报文的种类):重装超时的处理——"当终点在预先规定的时间内不能收到一个数据报的全部数据报片时,就把已收到的数据报片都丢弃,并向源点发送时间超过报文"。这句同时印证了重装发生在终点

相关知识

IPv4 数据报格式ICMP 协议IPv6 基础以太网与 IEEE 802.3

真题练习