RFC 1071中说到校验和的定义:html
(1) Adjacent octets to be checksummed are paired to form 16-bit integers, and the 1's complement sum of these 16-bit integers is formed.
(2) To generate a checksum, the checksum field itself is cleared, the 16-bit 1's complement sum is computed over the octets concerned, and the 1's complement of this sum is placed in the checksum field.
(3) To check a checksum, the 1's complement sum is computed over the same set of octets, including the checksum field. If the result is all 1 bits (-0 in 1's complement arithmetic), the check succeeds.
IP校验和是报头中全部16位字的补码之和的16个位的补码。
许多人可能会问的一个问题是“1的补码和是多少?”。这是由于全部计算机都使用‘2的补码’表示,而不使用‘1的补码’。如下简要介绍。网络
那么什么是 1的补码(ones's complement sum)、什么是2的补码(two's complement sum):this
1的补码(ones's complement sum): 也称为反码。之因此称为“反码”,是由于反码表示的负数,在形式上能够看作对其所对应正数(其相反数)的“按位求反”(将全部0换为1,1换为0),例如,十进制数6,用8位二进制数表示为00000110,则-6表示为11111001。spa
这一名称十分直观地体现了反码的外貌,通俗易懂。可是“1的补码”这个名字就有点让人摸不着头脑了,彻底不明白是什么意思。其实,这是翻译的锅。 反码的英文叫作 Ones' complement (注意不是 One's complement),意即“(复数个)一的补”。因为汉语中名词不能经过词形变化来体现单复数,咱们没法经过译名来体会这个名字的含义。仍取上面的例子,咱们将反码的+6与-6按二进制加法相加,发现获得了“一串一”。.net
仔细想一想能够发现,任意一对相反数的反码的“和”都是一串一,因此咱们能够这样定义负数N的n位二进制反码:
这即是反码叫作“(复数个)一的补”的缘由。翻译
而后你是否是觉得“二的补”就是这样:3d
并不!二进制数中不会出现“2”。事实上,“2的补码”,英文是 Two's complement (而不是Twos' complement),因此它是“(一个)2的补码”,与“1的补码”其实不是同一个意思。负数的补码的定义以下:
这里的“two”就是指上式中的“2”。code
总结:orm
“1的补码”是指“以一串一为模求补” “2的补码”是指“以二的n次幂为模求补”
Binary | Decimal | Hex |
---|---|---|
00000000 | 0 | 00 |
00000001 | 1 | 01 |
00000010 | 2 | 02 |
00000011 | 3 | 03 |
11111111 | -1 | FF |
11111110 | -2 | FE |
11111101 | -3 | FD |
两个整数相加:
-3 + 5 = 2
FD + 05 = 01 02
丢弃进位(01)会获得正确的结果。htm
Binary | Decimal | Hex |
---|---|---|
00000000 | 0 | 00 |
00000001 | 1 | 01 |
00000010 | 2 | 02 |
00000011 | 3 | 03 |
11111111 | -0 | FF |
11111110 | -1 | FE |
11111101 | -2 | FD |
11111100 | -3 | FC |
一样的两个数相加:
-3 + 5 = 2
FC + 05 = 01 01
将进位(01)相加到低位(01)会获得正确的结果:
01 + 01 = 02
所以,1的补码和是经过对数字求和并在结果中加上一个或多个进位来完成的。
假设咱们有一个使用2的补码的8位机器而且发送一个数据包:
FE 05 00
00是校验和字段。
让咱们计算和校验网络校验和,这个普通的相加获得的结果:
FE + 05 = 01 03
1的补码和要求将进位(01)加到结果里:
03 + 01 = 04
因此FE + 05的1的补码和是04。
1的补码的1的补码和就是:
~04 = FB
数据包将会是:
FE 05 FB
如今,在接收端咱们将收到的字节相加,包括校验和:
FE + 05 + FB = 01 FE
这1的补码和是:
FE + 01 = FF = -0
校验和为-0说明是ok的。
伪数据包:
01 00 F2 03 F4 F5 F6 F7 00 00
(00 00 是校验和字段)
按16位分组:
0100 F203 F4F5 F6F7
计算求和:
0100 + F203 + F4F5 + F6F7 = 0002 DEEF (值存在32位内存)
将进位(0002)加到结果里,获得1的补码和:
DEEF + 002 = DEF1
计算1的补码和的1的补码(Calculate 1's complement of the 1's complement sum):
~DEF1 = 210E
包含校验和(21 0E)的数据包:
01 00 F2 03 F4 F5 F6 F7 21 0E
在接收端:
0100 + F203 + F4F5 + F6F7 + 210E = 0002 FFFD
FFFD + 0002 = FFFF
校验结果为FFFF,说明校验经过。
在2的补码机上使用1的补码加法可能看起来很笼统。可是,这种方法有其自身的优势。
可能最重要的是它是字节序独立的。小端字节序计算机将LSB(Least Significant Bit--最低有效位)放在最后(例如Intel处理器)。 大端字节序计算机将LSB放在首位(例如IBM大型机)。当将进位加到LSB上以造成1的补码和时(请参见示例),咱们加03 + 01仍是01 + 03都不要紧。结果是相同的。
一、LSB(Least Significant Bit)--最低有效位
LSB表明二进制中最小的单位,能够用来指示数字很小的变化。也就是说,LSB是一个二进制数字中的第0位(即最低位),具备权值为2^0,能够用来检测数的奇偶性。
二、MSB(Most Significant Bit)--最高有效位
MSB表明一个n位二进制数字中的n-1位,具备最高的权值2^(n-1).对于有符号的二进制数,负数采用反码或补码形式,此时MSB用来表示符号,msb为1表示负数,0表示正数。
其余好处包括易于检查传输和校验和计算,以及经过仅更新已更改的IP协议的字段来加快计算速度的多种方法。
未完待续
参考:
一、《Short description of the Internet checksum》
二、《反码,补码为何又叫“一的补”,“二的补”?》
三、RFC 1071四、