校验和计算原理_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)
上一篇 2025年7月16日 上午8:22
下一篇 2025年7月16日 上午9:01


相关推荐

  • java 二维数组排序

    java 二维数组排序①使用Comparator生成一个比较器对象初始化数组:int[][]arr=newint[m][n];排序规则:先按数组的第一个元素进行升序排序,若第一个元素相等,则按照第二个元素进行升序排序。使用API:Arrays.sort()(T[]a,Comparator<?superT>c),该API根据给定的比较器(设定排序方式)对指定的数组进行排序。代码实现:Arrays.sort(arr,newComparator<int[]>(){

    2022年6月5日
    40
  • ASP.NET MVC 教程学习「建议收藏」

    ASP.NET MVC 教程学习「建议收藏」1.Why:为什么需要ASP.NETMVC本章主要为大家汇总了为什么学习Asp.netMVC替代WebForms,产生ASP.NETMVC的需求是什么,只有更好的理解了为什么需要MVC,出于什么目的开发的MVC框架,用MVC框架来弥补什么或是提升什么,才能利用其开发出最高效最满意的Web系统。 为什么会出现ASP.NET平台下的MVC框架?说明:本文摘自InfoQ,是作者JonathanAllen2007年发布的一篇的文章,首先描述了WebForms的优

    2022年7月22日
    13
  • 成功解决urllib.error.URLError urlopen error Errno 11004 getaddrinfo failed

    成功解决urllib.error.URLError urlopen error Errno 11004 getaddrinfo failed成功解决 urllib error URLError urlopenerror Errno11004 getaddrinfof 目录解决问题解决思路解决方法第一步 找到新的网址第二步 查看源代码 将网址覆盖即可 解决问题 urllib error URLError urlopenerror Errno11004 getaddrinfof 解决思路 urll urlopenerror Errno11004 getaddrinfof urlopenerror Errno11004 getaddrinfof

    2026年3月17日
    1
  • python怎么把字体调大_python修改字体

    python怎么把字体调大_python修改字体Pycharm4.5是一款非常强大的Python代码编辑器,其具备了易于上手、功能强大等特点,深受广大开发人员的青睐,而在使用的过程中,我们常常需要设置字体的大小以及背景颜色等参数,从而能够为用户带来更好的代码编辑效果,而部分刚入手的用户可能还不知到如何进行设置,小编这里为用户带来了Pycharm4.5设置字体大小与背景颜色的操作操作教程,有需要的用户赶紧来了解一下吧,想必能够为用户带来帮助!方法…

    2022年8月26日
    10
  • modelsim-win64-10.4-se 下载、安装、破解全攻略(屡试不爽)

    modelsim-win64-10.4-se 下载、安装、破解全攻略(屡试不爽)本教程包括软件下载、破解文件下载、安装破解方法,助你一次成功。软件安装好了却不能用,想必大家都有过这样的痛苦和无奈。这款软件的破解花了我整整一个下午的时间,期间在网上找了各种方法尝试均以失败告终,差点让我放弃破解而着手去换操作系统。网上的方法多存在着疏漏和差错,所以这也是我写次教程的初衷,希望能帮到大家,少走弯路。本人使用系统声明:win864位专业版以及win1064位安装

    2022年5月24日
    167
  • 腾讯混元HY 2.0正式发布:推理能力与实用性双突破,引领国内大模型新标杆

    腾讯混元HY 2.0正式发布:推理能力与实用性双突破,引领国内大模型新标杆

    2026年3月13日
    3

发表回复

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

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