zoukankan      html  css  js  c++  java
  • Sword 校验和计算

    // IP首部校验和的计算
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    unsigned short checksum(const void *, unsigned int);
    
    #define CHECK_SIZE 24
    
    /*
    知识补充:
        为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16 bit进行二进制反码求和(整个首部看成是由一串16 bit的字组成),
        结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,
        因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。
        但是不生成差错报文,由上层去发现丢失的数据报并进行重传。
    */
    
    union DataIp
    {
        char data[CHECK_SIZE];
        unsigned short s[CHECK_SIZE/2];
    };
    
    void test()
    {
        unsigned short ck = 0;
        union DataIp ip;
    
        strcpy(ip.data, "123456789abcdef");
        /*
        设计说明:
            假定s[3]为校验位
        */
        ip.s[3] = 0;    // 首先把检验和字段置为0
    
        // 发送方
        printf("send data is %s .
    ", ip.data);
        // 校验和计算
        ip.s[3] = checksum(ip.data, CHECK_SIZE);
    
        // 接收方进行校验和计算
        ck = checksum(ip.data, CHECK_SIZE);
    
        printf("last check sum is %hu .
    ", ~ck);
    
    }
    
    unsigned short checksum(const void *data, unsigned int size)
    {
        const unsigned char space = sizeof(unsigned short) * 8;         // 单位校验长度(单位bit)
        unsigned short buffer;                                          // 缓冲区
        const unsigned short *p = (const unsigned short *)data;         // 偏移指针
        unsigned int total = 0;
    
        // 1.参数校验
        if (NULL == data || 0 == size)
        {
            return total;
        }
    
        // 2,逐位进行运算
        while (size > 1)
        {
            buffer = *p++;
            /*
            设计说明:
                为什么不是 total += ~buffer;
                因为 buffer 的类型是 unsigned short ,当进行+=运算时,编译器会将 buffer 转成unsigned int类型,
                此时 ~buffer操作会导致高位全是1,得出的total结果错误
            */
            total += (unsigned int)(~buffer)&0xffff;
            size -= sizeof(unsigned short);
        }
    
        // 3.剩余位填充
        if (size)
        {
            buffer = 0;
            memcpy(&buffer, p, size);
            total += (unsigned int)(~buffer)&0xffff;
        }
    
        // 4.进位处理
        /*
        知识补充:
            校验位是16bit,但是total却是32bit,需要将产生的进位加到低位
           
        */
        while (total >> space)
        {
            //循环操作,直到没有进位为止
            total = (total >> space) + (total & 0xffff);
        }
    
        return (unsigned short)total;
    }
    
    
    int main(int argc, char *argv[])
    {
        test();
        getchar();
        return 0;
    }
  • 相关阅读:
    sql性能调优的注意项
    mybatis获取刚插入数据的ID
    mysql
    JQuery
    JS
    css
    web前端
    python爬虫
    socket编程
    python基础
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/12878523.html
Copyright © 2011-2022 走看看