1.奇偶校验

定义:
奇偶校验是一种最基础的错误检测方法,通过在数据后面增加一个校验位,使得整个数据中“1”的个数为奇数(奇校验)或偶数(偶校验),接收端据此判断数据是否在传输过程中出错。
奇校验(Odd Parity) 在发送的数据后加一个校验位,使得整个数据(包括校验位)中“1”的总数为奇数。
例:数据
10001100中有 3 个“1”(奇数),校验位设为0→ 总数仍为奇数。如果数据
10001101中有 4 个“1”(偶数),则校验位设为1→ 总数变为奇数。
偶校验(Even Parity) 在发送的数据后加一个校验位,使得整个数据(包括校验位)中“1”的总数为偶数。
例:数据
10001100中有 3 个“1”(奇数),校验位设为1→ 总数变为偶数。如果数据
10001101中有 4 个“1”(偶数),校验位设为0→ 总数仍为偶数。
验证:
发送端和接收端约定好使用偶校验时,当数据有一位发生改变,接收端会发现不符合偶校验正确,即发现错误,例如:
原数据:
1010 0错误数据:
0010 0统计“1”的个数 = 1 → 奇数 → 不符合偶校验。
接收端发现错误 → 报告数据损坏。
存在的问题:
问题在于如果同时有两位或偶数位数据发生改变,则无法检测,即该方法只能检验奇数位发生错误的数据,例如:
原数据:
1010 0错误数据:
0000 0统计“1”的个数 = 0 → 偶数 → 符合偶校验。
接收端未发现错误。但其实有两位发生错误。
2.校验和
定义
在 IPv4 数据报的首部中,有一个 16 位的首部检验和字段。
它的作用是:对 IP 首部(不包括数据部分)进行校验,保证首部在传输过程中没有发生比特错误。
如果接收端计算出的检验和与首部中的值不一致,就说明首部损坏,数据报会被丢弃。
示例数据与准备
示例首部(20 字节,不含选项) 为了演示,我们用一段典型的 IPv4 首部的十六进制(把“首部检验和”字段先置 0):
版本/IHL/TOS:
45 00总长度:
00 54标识:
00 00标志/片偏移:
40 00TTL/协议:
40 01首部检验和(置零):
00 00源地址:
C0 A8 00 01(192.168.0.1)目的地址:
C0 A8 00 C7(192.168.0.199)
按 16 位分组(两个字节一组) 这些字节组合成 10 个 16 位字(十六进制):
0x4500, 0x0054, 0x0000, 0x4000, 0x4001, 0x0000, 0xC0A8, 0x0001, 0xC0A8, 0x00C7
计算“首部和”(16 位一补加法)
规则
依次把所有 16 位字相加(普通无符号加法)。
如果产生了进位(超过 16 位),将溢出的高位加回到低 16 位,这就是所谓的“回卷”或“折叠进位”。
逐步相加示例(用十六进制呈现)
初始和: sum = 0
加
0x4500→ sum=0x4500加
0x0054→ sum=0x4554加
0x0000→ sum=0x4554加
0x4000→ sum=0x8554加
0x4001→ sum=0xC555加
0x0000→ sum=0xC555加
0xC0A8→ sum=0x186FD回卷:sum=0x86FD+0x1=0x86FE= 0x86FE
加
0x0001→ sum=0x86FF加
0xC0A8→ sum=0x147A7回卷:sum=0x47A7+0x1= 0x47A8
加
0x00C7→ sum=0x487F
得到首部和(未取一补): sum=0x487F
取一补得到“首部检验和”
取一补(按位取反)
0x487F 取反得到 0xB780
填入首部检验和字段 将
0xB780写入原来置零的“首部检验和”字段(两个字节,大端序:B7 80)。
接收端校验方法
再次求一补和 接收端对整个首部(包含你刚写入的
0xB780)再做一遍同样的 16 位一补加法。判定正确性
正确报文的结果应为全 1:
0xFFFF。也就是说,接收端把首位到检验和的之间所有数按上面的方法相加得到的就是
0x487F与检验和0xB780相加(做一补加法),结果就是0xFFFF,即是二进制的1111 1111 1111 1111,再把和值取反得到0000 0000 0000 0000。这样方便于底层硬件计算。
问题

当0100 0101 0000 0000与0000 0000 0010 1000中红色位置的值发生改变时,
0100 0101 0000 0000->0100 0101 0010 0000,
0000 0000 0010 1000->0000 0000 0000 1000
他们的和依旧为0100 0101 0010 1000,检验和无法发现错误。
3.CRC
定义:
CRC(循环冗余校验,Cyclic Redundancy Check)是一种常用的差错检测方法,它把数据看作一个二进制多项式,用预先约定好的“生成多项式”去做模 2 除法,余数就是 CRC 校验码。发送方把这个余数附在数据后面,接收方再用同样的方法计算并比对,如果不一致就说明数据出错。
二进制不借位减法:(==异或运算)


当有一个n位的除数,则需在被除数后添加n-1位0,然后进行二进制不借位减法,也是将二个数进行异或运算,
将余数101补充到原来的被除数后,得到1001 1010 101,把这个数发给接收方,接收方接到后进行同样的除法运算
得到的结果应该是0000,如果得到的结果不是0,那就说明出错了,把余数冗余作为被除数进行循环相除,就是循环冗余校验了,这个方法被广泛使用,虽然也会出错,但概率极小,效果比上面两种方法好。