校验和

1、校验和是用于检测传输过程中可能产生的错误,将其置于数据后,随数据一同发送,接收端通过同样的算法进行检查,若正确就接受,错误就丢弃

校验和C源代码:


unsigned short checksum(unsigned char *buf,int len)
{
        unsigned int sum=0;          //1
        unsigned short *cbuf;        //2
        cbuf=(unsigned short *)buf;    //3


        while(len>1)                        //4
        {
                sum+=*cbuf++;
                len-=2;
        }
        if(len)                               //5
        {
                sum+=*(unsigned char *)cbuf;
        }


        while(sum>>16)     //6
        {
                sum=(sum>>16)+(sum&0xffff);
        }
return (~sum);     //7
}


1.定义检验和变量,32位的 int型


2.定义接受的字符,16位的short int 型,因为校验和就是一个基于16位的反码计算原理,计算机制为1的补码,对称的系统,ffff和0000分别为-0和+0,afff和7ffff分别是-32767和+32767,这与我们平时遇到的2的补码机制不同

为什么要基于1的补码并进行反码求和机制?

因为考虑到大端和小端字节序的问题,在不同架构的处理器的保存方式不同,如果用常规的加法,接收端和发送端可能由于处理器架构不同会出现校验和的不同,但用反码求和,不管是大端还是小端,最终得到的结果都一样,不会影响到最终的校验和。


3.将8位的char类型转换成16位的short型 


4.进行校验和的加法,都是基于16位的,每次进行16位移动


5.若len为奇数,要加上最后的8bit,也就是最后一个字节


6.将得到的校验和右移16位,这里是无符号的,也就是算术右移,后面一句也就是将sum的高16位和低16位做加法,这就是1的补码机制,最高位进位加到最低位。


7.最后返回校验和,是一个二进制的反码


2、checksum-8位和16位校验和代码示例


  1. // linux 系统编译通过  
  2. // gcc filename.c -o filename  
  3. // ./filename  
  4.   
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7.   
  8. unsigned char ip_hdr_8[] =   
  9. {  
  10.     0x45,0x00,  
  11.     0x00,0x3c,  
  12.     0x00,0x00,  
  13.     0x00,0x00,  
  14.     0x40,0x01,  
  15.     0x00,0x00,  // checksum  
  16.     0xc0,0xa8,  
  17.     0x01,0x25,  
  18.     0xda,0x3c,  
  19.     0x06,0x82  
  20. };  
  21.   
  22. unsigned short ip_hdr_16[] =   
  23. {  
  24.     0x4500,  
  25.     0x003c,  
  26.     0x0000,  
  27.     0x0000,  
  28.     0x4001,  
  29.     0x0000,     // checksum  
  30.     0xc0a8,  
  31.     0x0125,  
  32.     0xda3c,  
  33.     0x0682  
  34. };  
  35.   
  36. unsigned int checksum_8(unsigned int cksum, void *pBuffer, unsigned int size)  
  37. {  
  38.     char num = 0;  
  39.     unsigned char *p = (unsigned char *)pBuffer;  
  40.    
  41.     if ((NULL == pBuffer) || (0 == size))  
  42.     {  
  43.         return cksum;  
  44.     }  
  45.      
  46.     while (size > 1)  
  47.     {  
  48.         cksum += ((unsigned short)p[num] << 8 & 0xff00) | (unsigned short)p[num + 1] & 0x00FF;  
  49.         size  -= 2;  
  50.         num   += 2;  
  51.     }  
  52.      
  53.     if (size > 0)  
  54.     {  
  55.         cksum += ((unsigned short)p[num] << 8) & 0xFFFF;  
  56.         num += 1;  
  57.     }  
  58.    
  59.     while (cksum >> 16)  
  60.     {  
  61.         cksum = (cksum & 0xFFFF) + (cksum >> 16);  
  62.     }  
  63.      
  64.     return ~cksum;  
  65. }  
  66.   
  67.   
  68. unsigned short checksum_16(unsigned short *addr,int len)  
  69. {  
  70.     unsigned short chksum;  
  71.     unsigned int sum = 0;  
  72.   
  73.     while(len > 1)  
  74.     {  
  75.         sum += *addr++;  
  76.         len -= 2;  
  77.     }  
  78.       
  79.     if(len == 1)  
  80.         sum += *(unsigned char*)addr;  
  81.           
  82.     sum = (sum>>16) + (sum & 0xffff);  
  83.     sum += (sum>>16);  
  84.     chksum = ~sum;  
  85.     return (chksum);  
  86. }  
  87.   
  88. void main()  
  89. {  
  90.     unsigned short chksum;  
  91.   
  92.     printf("--------------------------------------------\n");  
  93.       
  94.     chksum = checksum_8(0,ip_hdr_8,sizeof(ip_hdr_8));  
  95.     printf("checksum_8 = 0x%04x \n",chksum);  
  96.     ip_hdr_8[10] = chksum >> 8;  
  97.     ip_hdr_8[11] = chksum & 0xff;  
  98.       
  99.     chksum = checksum_8(0,ip_hdr_8,20);  
  100.     if(chksum)  
  101.         printf("Checksum_8 is incorrect! \n");  
  102.     else  
  103.         printf("Checksum_8 is correct! \n");  
  104.   
  105.     printf("--------------------------------------------\n");  
  106.       
  107.     chksum = checksum_16(ip_hdr_16,sizeof(ip_hdr_16));  
  108.     printf("checksum_16 = 0x%04x \n",chksum);  
  109.     ip_hdr_16[5] = chksum;  
  110.       
  111.     chksum = checksum_16(ip_hdr_16,20);  
  112.     if(chksum)  
  113.         printf("Checksum 16 is incorrect! \n");  
  114.     else  
  115.         printf("Checksum 16 is correct! \n");  
  116.       
  117.     printf("--------------------------------------------\n");  
  118. }  


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值