5checksum(校验和)的实现
Posted sbtblogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5checksum(校验和)的实现相关的知识,希望对你有一定的参考价值。
一、8位校验和的实现
1.发送端计算8位校验和的步骤:
(1)把校验和字段设置为0。
(2)把需要校验的数据看成以8位为单位的数字组成,依次进行求和,得到的和二进制求反码,再加上1,最终得到校验和。
(3)把得到的结果存入校验和字段中。
2.接收端校验校验和步骤:
(1)把需要校验的内容(包括校验和字段)看成以8位为单位的数字,依次进行二进制反码求和,如果结果是0表示正确,否则表示错误。
3.实现代码:
1 static unsigned char sg_ucSeq = 0; 2 typedef struct 3 { 4 unsigned long hid; 5 unsigned long cid; 6 unsigned char type; 7 unsigned char len; 8 unsigned char checksum; 9 unsigned char seq; 10 11 unsigned char userData[MAX_USER_DATA_SIZE]; 12 }DATA_T; 13 14 #define MAX_USER_DATA_SIZE 40 15 #define DATA_HEADER_LEN (sizeof(DATA_T) - MAX_USER_DATA_SIZE) 16 17 unsigned char MakeCheckSum8(DATA_T *pData) 18 { 19 unsigned char ucCheckSum = 0; 20 unsigned char ucNum; 21 unsigned char *pucDat = (unsigned char *)pData; 22 23 // 以1byte为单位依次相加 24 for(ucNum=0;ucNum<pData->len;ucNum++){ 25 ucCheckSum += pucDat[ucNum]; 26 } 27 28 // 二进制求反码,并加1,得到校验和 29 ucCheckSum = ~ucCheckSum; 30 ucCheckSum++; 31 32 return ucCheckSum; 33 } 34 35 unsigned char CheckData8(DATA_T *pData) 36 { 37 unsigned char ucCheckSum = 0; 38 unsigned char ucNum; 39 unsigned char *pucDat = (unsigned char *)pData; 40 41 for(ucNum=0;ucNum<pData->len;ucNum++){ 42 ucCheckSum += pucDat[ucNum]; 43 } 44 45 return ucCheckSum; 46 } 47 void create_common_msg(DATA_T *pfdata, unsigned char type, unsigned char *pdata, int len) 48 { 49 memset(pdata, 0, sizeof(DATA_T)); 50 51 pfdata->clientid = 0x12345678; 52 pfdata->type = type; 53 pfdata->len = DATA_HEADER_LEN + len; 54 pfdata->checksum = 0; 55 pfdata->seq = sg_ucSeq++; 56 57 if (len > 0) 58 { 59 memcpy(pfdata->userData, pdata, len); 60 } 61 62 pfdata->checksum = MakeCheckSum8(pdata); 63 64 return; 65 }
二、16位校验和的实现
1.计算校验和的步骤:
(1)把校验和字段设置为0。
(2)把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和。
(3)把得到的结果存入校验和字段中。
另外UDP、TCP数据报的长度可以为奇数字节,因为计算时是16位为单位,所以此时计算校验和时需要在最后增加一个填充字节0(只是计算校验和用,不发送出去)。
2.接收端校验校验和步骤:
(1)把需要校验的内容(包括校验和字段)看成以16位为单位的数字,依次进行二进制反码求和,如果结果是0表示正确,否则表示错误。
3.二进制反码求和步骤:
(1)二进制反码求和,就是先把这两个数取反,然后求和,如果最高位有进位,则向低位进1。
(2)另外,先取反后相加与先相加后取反,得到的结果是一样的。因此实现代码都是先相加,最后再取反。
4.实现代码:
1 static inline unsigned short make_check_sum16(const unsigned short *buf, int size) 2 { 3 unsigned long chksum = 0; 4 5 //16位为单位数字相加 6 while(size>1) 7 { 8 chksum += *buf++; 9 size -= sizeof(unsigned short ); 10 } 11 12 //长度奇数情况 13 if(size) 14 { 15 chksum += *((unsigned char *)buf); 16 } 17 18 //高位有进位,进位到低位,下面两行代码保证了高16位为0。 19 while (chksum >> 16) 20 { 21 chksum = (chksum >> 16) + (chksum & 0xffff); 22 } 23 24 //最后取反 25 return (unsigned short )(~chksum); 26 }
以上是关于5checksum(校验和)的实现的主要内容,如果未能解决你的问题,请参考以下文章