码迷,mamicode.com
首页 > 其他好文 > 详细

5、checksum(校验和)的实现

时间:2020-01-22 14:50:42      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:结果   comm   const   增加   oid   包括   mem   struct   font   

一、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 }

5、checksum(校验和)的实现

标签:结果   comm   const   增加   oid   包括   mem   struct   font   

原文地址:https://www.cnblogs.com/sbtblogs/p/12228406.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!