浅谈 IPv4 中的首部检验和字段
tags: 网络浅谈 IPv4 中的首部检验和字段
IP 数据报格式中存在 16 位的首部检验和,该字段只用于检测数据报首部,不检验数据部分。它不采用常用的 CRC 技术来进行差错检验而采用简单的计算方法。这是为什么呢?

IP 协议设计的核心目标是“尽力交付”,而非端到端的绝对可靠(可靠性由上层协议如 TCP 保障):
- 数据部分(如 TCP/UDP 报文、应用数据)可能被中间路由设备分片,若每次转发都检测数据,会大幅增加设备算力开销;
- 数据的错误可由接收端的上层协议(如 TCP 的检验和、应用层的校验机制)最终验证,IP 仅需确保“路由关键信息(首部)正确”,避免因首部错误导致数据报被错发或丢弃。
IP 协议对数据报首部的差错检测过程

发送端:计算首部检验和(生成阶段)
发送端(如源主机、转发路由)在封装 IP 数据报时,需先计算首部的检验和,并填入 IP 首部的“检验和字段”。具体步骤如下:
-
初始化检验和字段为 0 先将 IP 首部中的“检验和”字段本身填充为全 0(因为检验和是对“首部所有字段”的校验,需排除自身初始值的干扰)。
-
拆分首部为 16 位(2 字节)的二进制组。例如:一个 20 字节(最小 IP 首部)的首部,会拆分为 10 个 16 位组(20 字节 ÷ 2 字节 / 组 = 10 组)。
-
对所有 16 位组进行“反码加法”,其核心是进位循环:将所有 16 位组依次相加,若某一步相加产生进位(即结果超过 16 位),则将“进位位”(最高位的 1)取下,加到结果的最低位,直至无进位或处理完所有组。
-
对加法结果取反,得到首部检验和将步骤 3 的最终加法结果(16 位)进行“按位取反”(0 变 1,1 变 0),得到的 16 位数即为“首部检验和”,并将其填入 IP 首部的“检验和字段”。至此,发送端完成 IP 首部的检验和生成,数据报可进入传输链路。
接收端:验证首部检验和(检测阶段)
接收端(如中间路由、目的主机)收到 IP 数据报后,需验证首部是否存在传输错误(如比特翻转、数据丢失等),步骤与发送端对称:
-
拆分首部为 16 位组(含检验和字段)接收端同样将 IP 首部(含发送端填入的检验和字段)拆分为多个 16 位组(拆分规则与发送端完全一致)。
-
对所有 16 位组再次执行“反码加法”与发送端步骤 3 相同,将所有 16 位组(包括检验和字段)依次进行反码加法,处理所有进位。
根据加法结果判断是否出错反码加法的结果有两种可能,对应两种结论:
结果为“16 位全 1”:说明首部无错误(发送端的检验和与首部其他字段的反码加法结果互补,接收端相加后恰好抵消为全 1),接收端可继续处理数据报(如路由转发、交给上层协议)。
结果非“16 位全 1”:说明首部存在传输错误(如某比特从 0 变为 1,导致加法结果偏离全 1),接收端会直接丢弃该数据报(不通知发送端,因 IP 无重传机制)。
IP 协议的差错检测具体案例
假设发送端要发送一个简化的 IP 数据报首部(仅包含关键字段,总长度为 20 字节,即 10 个 16 位组),需要计算首部检验和;接收端收到后验证该检验和,判断首部是否出错。
组1:0x4500 组2:0x003C 组3:0x1C46 组4:0x0000 组5:0x0600 组6:0x0000 组7:0xC0A8 组8:0x0001 组9:0xC0A8 组10:0x00021.发送端计算首部检验和
① 检验和字段初始化
组 6 保持为 0,确保计算不包含自身初始值。
② 反码加法计算(逐组累加,处理进位)
反码加法规则:累加结果若超过 16 位(即产生进位),将进位位(最高位的 1)加到结果的最低位,循环处理直至无进位。
计算过程(十六进制):
第 1-5 组累加:0x4500 + 0x003C = 0x453C
0x453C + 0x1C46 = 0x6182(无进位)
0x6182 + 0x0000 = 0x6182
0x6182 + 0x0600 = 0x6782(前 5 组总和)
加入第 6 组(0x0000):0x6782 + 0x0000 = 0x6782
加入第 7 组(0xC0A8):0x6782 + 0xC0A8 = 0x1282A(产生进位 1,保留低 16 位 0x282A,加进位 1 → 0x282B)
加入第 8 组(0x0001):0x282B + 0x0001 = 0x282C(无进位)
加入第 9 组(0xC0A8):0x282C + 0xC0A8 = 0xE8D4(无进位)
加入第 10 组(0x0002):0xE8D4 + 0x0002 = 0xE8D6(最终累加结果,无进位)③ 取反得到检验和
对 0xE8D6 按位取反(十六进制取反公式:0xFFFF - 0xE8D6 = 0x1729):首部检验和 = 0x1729
发送端将检验和填入组 6,最终发送的 10 个组为:组1:0x4500 组2:0x003C 组3:0x1C46 组4:0x0000 组5:0x0600 组6:0x1729(检验和) 组7:0xC0A8 组8:0x0001 组9:0xC0A8 组10:0x00022.接收端验证检验和
① 拆分 10 个 16 位组(含检验和 0x1729)
② 反码加法验证(核心步骤) 计算过程:前 5 组之和:0x4500 + 0x003C + 0x1C46 + 0x0000 + 0x0600 = 0x6782(同发送端)
加上后 5 组(含检验和 0x1729):
0x6782 + 0x1729 = 0x7EA B(0x6782 + 0x1729 = 0x7EAB)
0x7EAB + 0xC0A8 = 0x13F53(进位 1,低 16 位 0x3F53 + 1 = 0x3F54)
0x3F54 + 0x0001 = 0x3F55
0x3F55 + 0xC0A8 = 0xFFFD(进位 1,低 16 位 0xFFFC + 1 = 0xFFFD)
0xFFFD + 0x0002 = 0xFFFF → 结果去反码,结果为 0,接收端判断“首部无错”,正常处理。补充说明
检验范围仅限首部如前所述,IP 检验和不包含数据部分(数据部分的错误由 TCP/UDP 的检验和或应用层机制处理),这是 IP“轻量路由”设计的体现。
反码加法的优势相比普通二进制加法,反码加法的“进位循环”机制能更全面地检测“比特翻转”错误,且计算过程无需额外存储进位(仅需对结果循环处理),适合路由设备的高速转发场景。
差错检测的局限性:IP 首部检验和仅能检测“奇数个比特错误”或“局部偶数个比特错误”,无法检测“完全互补的偶数个比特错误”(如某两个比特同时从 0 变 1 和 1 变 0,反码加法结果仍可能为全 1)。但这种极端情况在实际传输中概率极低,检验和机制已能满足 IP 路由的可靠性需求。
每跳转发都需重新计算检验和中间路由转发数据报时,若修改了首部字段(如“生存时间 TTL”减 1、“选项字段”调整),必须重新计算检验和(先将检验和字段设为 0,重复发送端步骤生成新检验和),因为原有检验和已与修改后的首部不匹配。
综上,IP 通过“首部检验和 + 反码加法”的机制,以低算力开销实现了首部差错的快速检测,确保路由关键信息的准确性,是 IP 协议“尽力交付”核心特性的重要支撑。
-