校验和计算原理_CRC校验原理及代码

校验和计算原理_CRC校验原理及代码校验和思路首先,IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit,算法基本上也是一样的。在发送数据时,为了计算数据包的检验和。应该按如下步骤:1、把校验和字段设置为0;2、把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;3、把得到的结果存入校验和字段中在接收数据时,计算数据包的检验和相对简单,按如下步骤:1、把首部看成以16位为单位的数字组成,依次进行二

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

校验和思路

首先,IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit,算法基本上也是一样的。

在发送数据时,为了计算数据包的检验和。应该按如下步骤:

1、把校验和字段设置为0;

2、把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;

3、把得到的结果存入校验和字段中

Jetbrains全家桶1年46,售后保障稳定

在接收数据时,计算数据包的检验和相对简单,按如下步骤:

1、把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

2、检查计算出的校验和的结果是否为0;

3、如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

虽然说上面四种报文的校验和算法一样,但是在作用范围存在不同:IP校验和只校验20字节的IP报头;而ICMP校验和覆盖整个报文(ICMP报头+ICMP数据);UDP和TCP校验和不仅覆盖整个报文,而且还有12个字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节)、TCP/UDP包长(2字节)。另外UDP、TCP数据报的长度可以为奇数字节,所以在计算校验和时需要在最后增加填充字节0(填充字节只是为了计算校验和,可以不被传送)。

校验和计算方法:

对一个无符号的数,先求其反码,然后从低位到高位,按位相加,有益处则向高位进1(和一般的二进制法则一样),若最高位有进位,则向最低位进1.

特点:关于二进制反码循环移位求和运算需要说明的一点是,先取反后相加与先相加后取反,得到的结果是一样的。

可结合性和可交换性

用A,B,C,D,E,F分别表示一个8位的二进制数(一个字节),用[A, B]这样的形式表示A*256+B,那么16位校验和可以用个如下形式给出

sum = [A,B]+’[C,D]+’[E,F];

其中, +’被表示二进制循环移位加法

可结合性:[A,B]+’[C,D]+’[E,F] = [A,B]+’([C,D]+’[E,F])
可交换性:[A,B]+’[C,D]+’[E,F] = [C,D]+’[A,B]+’[E,F]

字节自主性

[A,B]+’[C,D]+’[E,F] = [B,A]+’([D,C]+’[F,E])

由于若最高位有进位,则向最低位进1 这样的特性,第15位到0位进位,第7位向第8位进位,所以,整个求和结果是一样的。

并行计算

有些机器的字处理长度是16的倍数,这样可以提高他的计算速度,由于可结合行,那么32位机器可以[A,B,C,D]+’…进行32校验和。

为什么使用二进制反码循环移位加法呢?

我们知道,计算机中有原码,反码,补码,为什么要使用二进制反码来计算校验和呢,而不是直接使用原码或者是补码呢?

二进制反码循环移位加法求和优点

  1. 不依赖系统是大端小端。即无论你是发送方计算机或者接收方检查校验和时,都不要调用htons或者ntohs,直接通过上面的算法就可以得到正确的结果。这个问题你可以自己举个例子,用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不同。

  2. 计算和验证校验和比较简单、快递。

举例:

对于一串16进制数据:0001f203f4f5f6f7

这里写图片描述

正常顺序是将高8位*256之后,即将高位向左移动8位,加上低8位,交换顺序反之

可以明显得到,二进制反码循环移位加法与字节序无关。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

void main(int argc, char *argv[])
{
    FILE *fp;
    char ch;
    unsigned char LowChar, HighChar;
    unsigned int count = 0, checksum = 0, byte = 0;
    unsigned long int sum = 0;


    //打开文件文本
    if ((fp = fopen("I:\\1.txt", "r")) == NULL)
    {
        printf("File cannot be opened!");
        system("pause");
        return;
    }
    printf("4位 -- sum\n");
    //从文本中读取字符
    while(1)
    {
        if ((ch = fgetc(fp))!=EOF)
        {
            count++;                        //从1开始计数
            if (ch != ' ')
            {
                //将一个16进制字符转化为整形
                if (ch >= '0' && ch <= '9')
                {
                    ch -= '0';
                }
                else if (ch >= 'a' && ch <= 'f')
                {
                    ch = ch-'a'+10;
                }
                else if(ch >= 'A' && ch <= 'F')
                {
                    ch = ch-'A'+ 10;
                }


                //计算8字节的累加值
                if (count%2 == 1)
                {
                    HighChar = ch << 4;     //作为一个字节的高四位
                }
                else
                {
                    LowChar = ch & 0x0f;    //作为一个字节的低四位
                    byte = HighChar|LowChar;//构成一个字节

                    //16位并行计算
                    if (count % 4 == 2)     //高8位与sum相加
                    {
                        sum += byte << 8;   
                    }
                    else if(count % 4 == 0) //低8位与sum相加
                    {
                        sum += byte;
                    }
                    printf("%04x -- %8lx \n", byte, sum);
                }
            }
            else 
            {
                count--;
            }
        }
        else
        {
            break;
        }
    }

    //如果16位sum产生进位,将进位移加到低位
    if ( sum >> 16)
    {
        checksum = ~(long(sum>>16)+long(sum&0x0000ffff));
    }
    printf("\n移位后sum: %x", (long(sum>>16)+long(sum&0x0000ffff)));
    printf("\nCheckSum1: %x", checksum);
    //避免再次进位 
    checksum = checksum&0x0000ffff;

    //输出校验和
    printf("\nCheckSum: %x\n", checksum);

    system("pause");
}

运行结果

这里写图片描述

参考博客:传送门

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214282.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android Studio 撤销(Ctrl+Z)的对应快捷键[通俗易懂]

    Android Studio 撤销(Ctrl+Z)的对应快捷键[通俗易懂]撤销(Ctrl+Z)前进一步(Ctrl+shift+z)vs中初始也是如此

    2022年8月27日
    3
  • 腾讯面试题目汇总[通俗易懂]

    腾讯面试题目汇总面试官提问1:自我介绍及项目经历关于这道题,每个人的项目经历都不太一样,所以各位朋友根据自己的实际情况来介绍吧,在这里就不多介绍了。面试官提问2:看你项目介绍中大量使用了Redis,那能不能介绍下Redis的主从同步机制呢?关于这道题,因为我在之前的文章也分析过Redis主从同步的机制,所以我从完整重同步和部分重同步两个阶段去分析的,结果也得到了面试官的认可。详细的完整重同步和部分重同步机制原理是什么样的,在这里就不展开介绍了,附上链接朋友们自行查…

    2022年4月4日
    40
  • MySQL呕血汇总–从基础到毕业【收藏篇】

    MYSQL目录前言一、MYSQL基础1.安装2.数据库介绍2.1.什么是数据库?2.2.实体(类)和表关系2.3.常见关系型数据库3.MYSQL基础操作❤重点❤3.1.启动关闭3.2.DDL(数据定义语言,这些语句定义不同的数据段、数据库、表、列、索引等数据库对象。常用语句关键字主要包括create,drop,alter等)3.2.1.操作数据库3.2.2.操作表3.3.DML(数据操作语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性。常用语句关键字主要包括insert,delete,upda

    2022年4月9日
    26
  • 基于tensorflow的LSTM 时间序列预测模型

    时间序列预测(曲线回归或曲线拟合),结构为训练数据生成-》隐藏输入层-》LSTM神经层-》隐藏输入层-》结果,也可以采用LSTM神经层-》全连接层(多层的普通神经网络)构成,训练效果未对比,与参数调优相关。参数说明:TIME_STEPS:RNN训练的步数,一次训练输入的序列长度;INPUT_SIZE:输入序列中,单个输入的维度,用于曲线拟合或者回归的话,维度即为1;BATCH_SIZE:训练的批…

    2022年4月9日
    41
  • linux用户环境变量和系统环境变量_Linux系统中删除文件的命令

    linux用户环境变量和系统环境变量_Linux系统中删除文件的命令linux环境变量和Windows的环境变量一样,分系统环境变量和用户环境变量,系统环境变量对所有用户有效,而用户环境变量只对当前用户有效,下面以jdk为例进行两种环境变量的配置。1.系统环境变量配置执行vim/etc/profile,JAVA_HOME为jdk所在目录:保存后执行source/etc/profile立即生效,执行java-version,出现jdk版本

    2022年9月13日
    0
  • mysql explain不准确_mysql explain预估剖析「建议收藏」

    mysql explain不准确_mysql explain预估剖析「建议收藏」引子:使用MySQL建立了一张表country,总共有才3121行记录。但是使用explainselectcount(*)fromcountry;的时候,发现行数rows达到6897,让我大吃一惊。mysql>explainselectcount(*)fromcountry;+—-+————-+———+——+————–…

    2022年10月17日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号