zoukankan      html  css  js  c++  java
  • IP/IGMP/UDP校验和算法

        校验和算法:IP、IGMP、UDP和TCP报文头部都有检验和字段,其算法都是一样的。

        IP、IGMP、UDP和TCP校验和的范围:仅报文头部长度。

        在发送数据时,为了计算数据包的检验和。应该按如下步骤:

        1、把校验和字段设置为0;

        2、把需要校验的数据看成以16位为单位的数子组成,依次进行二进制反码求和(需将溢出位加在低位上);

        3、把得到的结果存入校验和字段中。

        在接收数据时,计算数据包的检验和相对简单,按如下步骤:

        1、把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

        2、检查计算出的校验和的结果是否为0;

        3、如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

        算法代码方案一,先取反后求和,实现如下:

      uBit16 checksum(uBit16 * buffer, int size)
      {
        uBit16 temp = 0;
        uBit16 answer = 0;
        unsigned long cksum = 0;

        while (size > 1)
        {
          answer = *buffer;
          temp = ~answer;
          cksum += temp;
          buffer++;
          size = size - sizeof(uBit16);
        }

        if (size)
        {
          answer = *buffer;
          temp = ~answer;
          cksum += temp;
        }

        while(cksum >> 16)
        {
          cksum = (cksum >> 16) + (cksum & 0xffff);
        }

        answer = (uBit16)cksum;

        return answer;
      }

        算法代码方案二,先求和后取反,实现如下:

      uBit16 checksum(uBit16 * buffer, int size)
      {
        uBit16 answer = 0;
        unsigned long cksum = 0;

        while (size > 1)
        {
          answer = *buffer;
          cksum += answer;
          buffer++;
          size = size - sizeof(uBit16);
        }

        if (size)
        {
          answer = *buffer;
          cksum += answer;
        }

        while(cksum >> 16)
        {
          cksum = (cksum >> 16) + (cksum & 0xffff);
        }

        answer = (uBit16)(~cksum);

        return answer;
      }

      说明:以上两种方案都可以正确实现校验和字段,先取反后求和与先求和后取反得到的结果是一样的。  

      注意:以上两种实现方案,都需要将溢出位加在低位上,如 while(cksum >> 16) {cksum = (cksum >> 16) + (cksum & 0xffff);}。传递包头大小时,以实际的包头大小来传递就可以了。

      校验和使用反码求和的优点是:不依赖系统是大端小端。即无论你是发送方计算机或者接收方检查校验和时,都不要调用htons或者ntohs,直接通过上面的算法就可以得到正确的结果。这个问题你可以自己举个例子,用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不同。

  • 相关阅读:
    Quartz.Net 作业调度后台管理系统,基于Extjs
    [备份]EntityFramework
    WebMisSharp升级说明,最新版本1.6.0
    AllPay(欧付宝)支付接口集成
    Paypal Rest Api自定义物流地址(跳过填写物流地址)
    根据IP获取国家
    ViewBag 找不到编译动态表达式所需的一种或多种类型,是否缺少引用?
    Extjs4 DateTimeField,日期时间控件完美版
    IOS Swift 训练
    .Net集成PayPal的Demo
  • 原文地址:https://www.cnblogs.com/xiehy/p/3286889.html
Copyright © 2011-2022 走看看