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 00

    • TTL/协议: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 位,这就是所谓的“回卷”或“折叠进位”。

  • 逐步相加示例(用十六进制呈现)

    1. 初始和: sum = 0

    2. 0x4500 → sum=0x4500

    3. 0x0054 → sum=0x4554

    4. 0x0000 → sum=0x4554

    5. 0x4000 → sum=0x8554

    6. 0x4001 → sum=0xC555

    7. 0x0000 → sum=0xC555

    8. 0xC0A8 → sum=0x186FD

      • 回卷:sum=0x86FD+0x1=0x86FE= 0x86FE

    9. 0x0001 → sum=0x86FF

    10. 0xC0A8 → sum=0x147A7

      • 回卷:sum=0x47A7+0x1= 0x47A8

    11. 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,那就说明出错了,把余数冗余作为被除数进行循环相除,就是循环冗余校验了,这个方法被广泛使用,虽然也会出错,但概率极小,效果比上面两种方法好。

是超级管理员哦