5、checksum(校验和)的实现

您所在的位置:网站首页 校验和是什么 5、checksum(校验和)的实现

5、checksum(校验和)的实现

#5、checksum(校验和)的实现| 来源: 网络整理| 查看: 265

一、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;ucNumlen;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;ucNumlen;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->cid = 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 check_sum(const unsigned short *buf, int size) 2 { 3 unsigned long chksum = 0; 4 5 //16位为单位数字相加 6 while(size>1) 7 { 8 chksum += *buf++; // 对传入的数据以unsigned short方式解析 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 }

三、32位校验和的实现

1.发送端计算32位校验和的步骤:

  (1)把校验和字段设置为0。

  (2)把需要校验的数据看成以32位为单位的数字组成,依次进行求和,得到的和二进制求反码,再加上1,最终得到校验和。

  (3)把得到的结果存入校验和字段中。

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

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

3.实现代码:

1 unsigned int make_checksum_32(unsigned char *pdata, int dataLen) 2 { 3 int len; 4 unsigned int chk = 0; 5 6 // 按照小端的方式计算4个字节的checksum 7 len = dataLen; 8 while (len >= 4) 9 { 10 chk += (unsigned int)pdata[0]; // ---- ---- ---- pdata[0] 11 chk += ((unsigned int)pdata[1]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3