通讯协议中的checksum校验和算法(转载)

文章目录
1 前言
2 具体思路
3 checksum的算法实现
3.1 checksum8
3.2 checksum16
4 linux中的校验和算法
5 测试
1 前言
说到检验和算法,比较熟悉的就是循环冗余算法(CRC),通常由CRC-8,CRC-16,以及CRC-32等,但是在资源相对比较紧张的一些平台上,运行CRC也比较吃力,或者对于需要进行快速校验的场合,所以这里可以使用简单的Checksum算法。

2 具体思路
这里以8位的Checksum为例,假设输入一组数据0XFF,0X05,0XC1,0X19;

用16位变量保存数据的累加和;
得到累积和之后,将累加和的高8位和低8位相加;
将累加和进行取反操作;
整体流程如下图所示;

最终结算得到的结果为0x20,下面会有相应的测试。

3 checksum的算法实现
3.1 checksum8
uint8_t m_checksum_08(const uint8_t pdata, uint32_t count)
{
register uint16_t sum = 0;
uint8_t
addr = (uint8_t *)pdata;
if(count <= 0){
goto error;
}
// Main summing loop
while(count >= 1)
{
sum = sum + *(uint8_t *) addr;
count --;
(uint8_t *) addr++;
}

// Add left-over byte, if any
if (count > 0)
sum = sum + *((uint8_t *) addr);

// Fold 16-bit sum to 8 bits
while (sum>>8){
    sum = (sum & 0xFF) + (sum >> 8);
}

return (uint8_t)(~sum);
error:
return 0;

}

3.2 checksum16
uint16_t m_checksum_16(const uint8_t pdata, uint32_t count)
{
register uint32_t sum = 0;
uint16_t
addr = (uint16_t *)pdata;
if(count <= 0){
goto error;
}
// Main summing loop
while(count >= 2)
{
sum = sum + *((uint16_t *) addr);
count = count - 2;
(uint16_t *) addr++;
//addr = addr + 2;
}
if(count == 1){
addr++;
sum = sum + *((uint8_t *) addr);
}

// Add left-over byte, if any
if (count > 0)
sum = sum + *((uint8_t *) addr);

// Fold 32-bit sum to 16 bits
while (sum>>16){
     sum = (sum & 0xFFFF) + (sum >> 16);
}

return(~sum);
error:
return 0;

}

4 linux中的校验和算法
下面是Linux中作为IP/TCP/UDP的校验和算法的例程,可以在linux/lib/checksum.c中找到,具体如下所示;

#include <linux/export.h>
#include <net/checksum.h>
#include <asm/byteorder.h>
#ifndef do_csum
static inline unsigned short from32to16(unsigned int x)
{
/* add up 16-bit and 16-bit for 16+c bit /
x = (x & 0xffff) + (x >> 16);
/
add up carry… */
x = (x & 0xffff) + (x >> 16);
return x;
}

static unsigned int do_csum(const unsigned char *buff, int len)
{
int odd;
unsigned int result = 0;
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
#ifdef __LITTLE_ENDIAN
result += (*buff << 8);
#else
result = *buff;
#endif
len–;
buff++;
}
if (len >= 2) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
len -= 2;
buff += 2;
}
if (len >= 4) {
const unsigned char *end = buff + ((unsigned)len & ~3);
unsigned int carry = 0;
do {
unsigned int w = *(unsigned int *) buff;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (buff < end);
result += carry;
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
if (len & 1)
#ifdef __LITTLE_ENDIAN
result += *buff;
#else
result += (*buff << 8);
#endif
result = from32to16(result);
if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
out:
return result;
}
#endif

5 测试
下面使用三组数据进行测试,代码如下所示;

uint8_t data01[] = { 0XFF,0X05,0XC1,0X19 };
uint8_t data02[] = { 0X11,0X12,0X12,0X04 };
uint8_t data03[] = { 0X11,0X12,0X12,0X04 };

int main()
{
printf(“test\r\n”);
printf(“data01 is 0x%02x \r\n”,m_checksum_08(data01,sizeof(data01)));
printf(“data02 is 0x%02x \r\n”,m_checksum_08(data02,sizeof(data02)));
printf(“data03 is 0x%02x \r\n”,m_checksum_08(data03,sizeof(data03)));

printf("data01 is 0x%04x \r\n",m_checksum_16(data01,sizeof(data01)));
printf("data02 is 0x%04x \r\n",m_checksum_16(data02,sizeof(data02)));
printf("data03 is 0x%04x \r\n",m_checksum_16(data03,sizeof(data03)));

return 0;

}

原文链接:https://blog.csdn.net/u010632165/article/details/107437096?utm_medium=distribute.pc_feed.none-task-blog-personrec_tag-2.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-personrec_tag-2.nonecase&request_id=5f1ff098f769fa6e5f5d1f67

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值