IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:
在发送数据时,为了计算IP数据包的校验和。应该按如下步骤:
(1)把IP数据包的校验和字段置为0;
(2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和;
(3)把得到的结果存入校验和字段中。
在接收数据时,计算数据包的校验和相对简单,按如下步骤:
(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;
(2)检查计算出的校验和的结果是否等于零(反码应为16个0);
(3)如果等于零,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
所谓的二进制反码求和,即为先进行二进制数取反,然后求和,如果最高位进一,则保存到最低位即可。
计算对IP首部检验和的算法如下:
(1)把IP数据包的校验和字段置为0;
(2)把首部看成以16位为单位的数字组成,依次进行二进制求和(注意:求和时应将最高位的进位保存,所以加法应采用32位加法);
(3)将上述加法过程中产生的进位(最高位的进位)加到低16位(采用32位加法时,即为将高16位与低16位相加,之后还要把该次加法最高位产生的进位加到低16位)
(4)将上述的和取反,即得到校验和。
二进制反码求和的计算方法:编辑
首先,我们计算如图B-1所示的部分和。我们把每一列相加,如果有进位,就加到下一列。注意以下几点:
1-->16
1 1-->15
* 1-->14
* 1-->13
* * 1 1-->12
* * * 1-->11
* * * * 1-->10
* * * * * 1 1-->9
* * * * * * * 1 1-->7
* * * * * * * * * 1-->6
* * * * * * * * * 1-->5
* * * * * * * * * 1-->4
* * * * * * * * * * 1-->3
* * * * * * * * * * * * 1 1-->2
* * * * * * * * * * * * 1-->第1的进位,以上同义(右起为第一列)
1 0 0 1 1 0 0 1 0 0 0 1 0 0 1 0
0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 1
1 0 1 0 1 0 1 1 0 0 0 0 0 0 1 0
0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1
0 1 0 1 0 0 1 1 0 1 0 1 0 1 0 0
0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 1
0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0
1 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 部分和
1 -->第15列的进位
1 -->第16列的进位
1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 和
0 1 1 0 1 0 0 1 0 0 0 1 0 0 1 1 校验和
图B-1 二进制记法的部分和
1,当我们加第1列(最右边一列)的时候,我们得到8。在二进制中,数8是1000。我们保留最右边的0,把其余的位进到第2列,第3列和第4列。
2,当我们加第2列时,我们计入从第1列来的进位。结果是7,它是二进制的0111。我们保留第一个位(最右边的),把其余011进位给第3列、第4列和第5列。
3,对每一列重复以上过程。
4,当我们加完最后一列时,我们有两个1没有列可以进行进位。这两个1在下一个步骤中应与部分和(Partial sum)相加。
B.1.2和
如果最后一列没有进位,那么部分和就是和。但是,如果还有额外的列(在本例中,有一个具有两行的列),那么就要把它加到部分和中,以便得出和。下图给出了这样的计算,我们得出了和。
1 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 部分和
1 0 -->第15,16列的进位
1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 和
0 1 1 0 1 0 0 1 0 0 0 1 0 0 1 1 校验和
图B-2 二进制记法的和与校验和
B.1.2校验和
在计算出和以后,我们把每一个位求反码,得出检验和。图B-2也给出了检验和。二进制计算方法其实可以转换为十进制计算,原理相同。
在发送数据时,为了计算IP数据包的校验和。应该按如下步骤:
(1)把IP数据包的校验和字段置为0;
(2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和;
(3)把得到的结果存入校验和字段中。
在接收数据时,计算数据包的校验和相对简单,按如下步骤:
(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;
(2)检查计算出的校验和的结果是否等于零(反码应为16个0);
(3)如果等于零,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
所谓的二进制反码求和,即为先进行二进制数取反,然后求和,如果最高位进一,则保存到最低位即可。
计算对IP首部检验和的算法如下:
(1)把IP数据包的校验和字段置为0;
(2)把首部看成以16位为单位的数字组成,依次进行二进制求和(注意:求和时应将最高位的进位保存,所以加法应采用32位加法);
(3)将上述加法过程中产生的进位(最高位的进位)加到低16位(采用32位加法时,即为将高16位与低16位相加,之后还要把该次加法最高位产生的进位加到低16位)
(4)将上述的和取反,即得到校验和。
二进制反码求和的计算方法:编辑
首先,我们计算如图B-1所示的部分和。我们把每一列相加,如果有进位,就加到下一列。注意以下几点:
1-->16
1 1-->15
* 1-->14
* 1-->13
* * 1 1-->12
* * * 1-->11
* * * * 1-->10
* * * * * 1 1-->9
* * * * * * * 1 1-->7
* * * * * * * * * 1-->6
* * * * * * * * * 1-->5
* * * * * * * * * 1-->4
* * * * * * * * * * 1-->3
* * * * * * * * * * * * 1 1-->2
* * * * * * * * * * * * 1-->第1的进位,以上同义(右起为第一列)
1 0 0 1 1 0 0 1 0 0 0 1 0 0 1 0
0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 1
1 0 1 0 1 0 1 1 0 0 0 0 0 0 1 0
0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1
0 1 0 1 0 0 1 1 0 1 0 1 0 1 0 0
0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 1
0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0
1 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 部分和
1 -->第15列的进位
1 -->第16列的进位
1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 和
0 1 1 0 1 0 0 1 0 0 0 1 0 0 1 1 校验和
图B-1 二进制记法的部分和
1,当我们加第1列(最右边一列)的时候,我们得到8。在二进制中,数8是1000。我们保留最右边的0,把其余的位进到第2列,第3列和第4列。
2,当我们加第2列时,我们计入从第1列来的进位。结果是7,它是二进制的0111。我们保留第一个位(最右边的),把其余011进位给第3列、第4列和第5列。
3,对每一列重复以上过程。
4,当我们加完最后一列时,我们有两个1没有列可以进行进位。这两个1在下一个步骤中应与部分和(Partial sum)相加。
B.1.2和
如果最后一列没有进位,那么部分和就是和。但是,如果还有额外的列(在本例中,有一个具有两行的列),那么就要把它加到部分和中,以便得出和。下图给出了这样的计算,我们得出了和。
1 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 部分和
1 0 -->第15,16列的进位
1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 和
0 1 1 0 1 0 0 1 0 0 0 1 0 0 1 1 校验和
图B-2 二进制记法的和与校验和
B.1.2校验和
在计算出和以后,我们把每一个位求反码,得出检验和。图B-2也给出了检验和。二进制计算方法其实可以转换为十进制计算,原理相同。