IP首部检验和

参考网址:
http://www.14edu.com/ligong/jisuanji/0Q4I5392010.html
http://wenku.baidu.com/view/a70e4c43336c1eb91a375d7a.html

  首部检验和字段是根据IP首部计算的检验和码。它不对首部后面的数据进行计算。ICMP、IGMP、UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。
  为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16 bit进行二进制反码求和(整个首部看成是由一串16 bit的字组成),结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。
  普通的IP首部长为20个字节,不带IP选项。位于数据包的第0x000E~0x0021字节(0x0000~0x000D为以太网首部)。普通IP首部的标志是第0x000E字节的值为0x45。计算之前应将第0x0018、0x0019两个字节置零。
  反码求和时,最高位的进位要进到最低位,也就是循环进位。因为IP包头和TCP整个报文段比较短(没达到2^17数量级),所以不可能导致4字节的sum溢出。32位数据的高位比特移位16比特,再加上原来的低16比特,实现高位溢出加到低位。

  定理1:原码+反码= value1,则value1的二进制全为1
  定理2:相加后取反=取反后相加

  接收数据时按如下步骤:
  1.把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。
  2.检查计算出的校验和的结果是否等于零(反码应为16个1)。
  3.如果等于零,说明校验和正确。否则,校验和错误,协议栈将抛弃这个数据包。
unsigned short checksum(unsigned short *buf, int size)
{
  unsigned long sum = 0;
  while(size > 1) {
    sum += *buf++;
    size -= sizeof(unsigned short);
  }
  if(size)  
    sum += *(unsigned char*)buf;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return (unsigned short)~sum; // 接收时sum值应为16个1,取反后为0。
}

测试数据:4500 0040 0E80 4000 8006 74FB AC14 9E0A AC14 8109

4500 0040 0E80 4000 8006 0000 AC14 9E0A AC14 8109 38B01 8B04
BAFF FFBF F17F BFFF 7FF9 FFFF 53EB 61F5 53EB 7EF6 674F5 74FB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值