计算数IP据报的校验和

IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法以下:算法


在发送数据时,为了计算数IP据报的校验和。应该按以下步骤:ide

(1)把IP数据报的首部都置为0,包括校验和字段。函数

(2)把首部当作以16位为单位的数字组成,依次进行二进制反码求和。spa

(3)把获得的结果存入校验和字段中。orm

在接收数据时,计算数据报的校验和相对简单,按以下步骤:it

 

(1)当接收IP包时,须要对报头进行确认,检查IP头是否有误,算法同上二、3步,而后判断取反的结果是否为0,是则正确,不然有错。class


一、发送方二进制

  i)将校验和字段置为0,而后将IP包头按16比特分红多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;方法

 

  ii)对各个单元采用反码加法运算(即高位溢出位会加到低位,一般的补码运算是直接丢掉溢出的高位),将获得的和的反码填入校验和字段;数据

 

  iii)发送数据包。

 

二、接收方

  i)将IP包头按16比特分红多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;

 

  ii)对各个单元采用反码加法运算,检查获得的和是否符合是全1(有的实现可能对获得的和会取反码,而后判断最终值是否是全0);

 

iii)若是是全1则进行下步处理,不然意味着包已变化从而丢弃之。须要强调的是反码和是采用高位溢出加到低位的,如3比特的反码和运算:100b+101b=010b(由于100b+101b=1001b,高位溢出1,其应该加到低位,即001b+1b(高位溢出位)=010b)。



现假如一数据报为45 00 05 D4 CA E0 40 00 75 06 70 D2 CA 62 39 64 C0 A8 00 02

根据IP数据报的格式能够看出它的首部校验字段为70 D2 它是怎么算出来的呢?

方法:咱们把首部校验字段即70 D2 用0000代替

4500+05D4+CAE0+4000+7506+0000+CA62+3964+C0A8+0002=38F2A

而后把进出来的一位与后4位再进行十六进制加法,8F2A+0003=8F2D

最后用FFFF减去算出来的结果就能够了即FFFF-8F2D=70D2

    



函数代码以下。

USHORT CheckSum(USHORT *buffer, int size)  

{  

    unsigned long cksum=0;  

    while (size > 1)   

    {  

        cksum += *buffer++;  

        size -= sizeof(USHORT);  

    }  

    if (size)   

    {  

        cksum += *(UCHAR*)buffer;  

    }    

    cksum = (cksum >> 16) + (cksum & 0xffff);  

    cksum += (cksum >>16);  

    return (USHORT)(~cksum);  

}  

相关文章
相关标签/搜索