• 校验和计算方法


    引用链接:困或 知之可否

    校验和计算方法

    1.哪些地方使用校验和

    • IP校验和:IP首部。
    • ICMP校验和:ICMP首部+ICMP数据;
    • UDP、TCP校验和:首部+数据+12个字节伪首部(源IP地址、目的IP地址、协议、TCP/UDP包长)。

    2.计算校验和的步骤:

    • 把校验和字段设置为0。
    • 把需要校验的数据看成以16比特为单位的数字组成,依次进行二进制反码求和。
    • 把得到的结果存入校验和字段中。
    • 另外UDP、TCP数据报的长度可以为奇数字节,因为计算时是16比特为单位,所以此时计算校验和时需要在最后增加一个填充字节0(只是计算校验和用,不发送出去)。

    3.接收端校验校验和步骤:

    • 把需要校验的内容(包括校验和字段)看成以16比特为单位的数字,依次进行二进制反码求和,如果结果是0表示正确,否则表示错误。

    4.二进制反码求和步骤:

    • 二进制反码求和,就是先把这两个数取反,然后求和,如果最高位有进位,则向低位进1。
    • 另外,先取反后相加与先相加后取反,得到的结果是一样的。因此实现代码都是先相加,最后再取反。

    5.实现代码:

    参考"算数位移"和逻辑位移

    
    static inline uint16_t check_sum(const uint16_t *buffer, int size){
        //cksum 4个字节无符号整型
        unsigned long cksum = 0;
     
        //16位为单位数字相加
        while(size>1){
            cksum += *buffer++;
            size -= sizeof(uint16_t);
        }
    
        //长度奇数情况
        if(size){
          cksum += *((unsigned char *)buffer);
        }
        
        //高位有进位,进位到低位,下面两行代码保证了高16位为0。
        cksum = (cksum>>16) + (cksum&0xffff);
        cksum += (cksum>>16);
        
        //最后取反
        return (uint16_t)(~cksum);
    }
    

    代码解析

    参数buffer是指向16位整数的指针,刚开始指向的是IP首部的起始地址,参数size是IP首部的大小。while循环是将IP首部的内容以16位为单元加在一起,如果没有整除(即size还有余下的不足16位的部分),则加上余下的部分,此时的cksum就是相加后的结果,这个结果往往超出了16位,因为校验和是16位的,所以要将高16位和计算得到的cksum再加工。
    再加工第一步:cksum = (cksum>>16) + (cksum&0xffff); sum>>16是将高16位移位到低16位,sum&0xffff是取出低16位,相加得到新的cksum。
    再加工第二步:cksum += (cksum>>16); 第一步相加时很可能会产生进位,因此要再次把进位移到低16位进行相加。  
    这样就加工好了,接下来就是取反,并强制转换为16位,这样就得到了最终的校验和。
    校验和计算出来了,接下来就是该如何校验:
    接收方进行校验时,也是对每16位进行二进制反码求和。接收方计算校验和时的首部与发送方计算校验和时的首部相比,多了一个发送方计算出来的校验和。因此,如果首部在传输过程中没有发生差错,那么接收方计算的结果应该为全一,因为接收方计算除校验和以外的部分得到值是校验和的反码,再加多出来的校验和当然是全一了。

  • 相关阅读:
    理解.NET中的异常(二)
    路径,文件,目录,I/O常见操作汇总(一)
    使用PInvoke.NET插件为托管代码添加Win32 API签名
    使用JavaScript检测浏览器的相关特性
    javascript中的变量
    曾经的你
    WinampMy Favorite Media Player
    新的开始,认真地写博客
    log4net的各种Appender配置示例
    使用GhostDoc为代码生成注释文档
  • 原文地址:https://www.cnblogs.com/sillycuckoo/p/13769613.html
Copyright © 2020-2023  润新知