关于校验算法的学习(学习以太网时遇到的)

关于校验算法的学习(学习以太网时遇到的)以太网的包头还是数据都会有校验,在FPGA上实现IP核时,用的是CRC校验,然后学习ICMP协议时,也看到一种校验算法,以此学习分析一下背后原理。

一、先看看ICMP的包格式,主要是写ping命令是用到(会有一篇专门将ping的c语言实现),所以只是展示与ping命令背后的ICMP规则。

(来自维基)

对于校验的研究暂时不需要理解其他数据的意思,维基对checksum的解释为

Checksum

Error checking data, calculated from the ICMP header and data, with value 0 substituted for this field. The Internet Checksum is used, specified in RFC 1071.

首先校验的是header+data,然后如果忽略补0,规则看RFC 1071,来看看这个文档。

二、在看这个文档之前先了解几个概念:2’s complement 和 1’s complement

其实这就是两种数值的表示方法,

先看2’s complement :这就是我们日常使用的,称为2补码系统。

看看维基大神的解释:

【This system is the most common method of representing signed integers on computers.[2] An N-bit two’s-complement numeral system can represent every integer in the range ?(2N???1) to +(2N???1 ? 1) 】

那怎么编码数据呢,看看:

For example, to find the 4-bit representation of ?5 (subscripts denote the base of the representation):

x = 510 therefore x = 01012

Hence, with N = 4:

x* = 2N ? x = 24 ? 510 = 100002 ? 01012 = 10112

The calculation can be done entirely in base 10, converting to base 2 at the end:

x* = 2N ? x = 24 ? 510 = 1110 = 10112

就是正数是其本身,如5为0101;负数最高位置一,然后将其他低位取反,再加一。

这就是常见的计算机编码方式。

这是编码图

再看看1’s complement

Positive numbers are the same simple, binary system used by two’s complement and sign-magnitude. Negative values are the bit complement of the corresponding positive value. The largest positive value is characterized by the sign (high-order) bit being off (0) and all other bits being on (1). The smallest negative value is characterized by the sign bit being 1, and all other bits being 0. The table below shows all possible values in a 4-bit system, from ?7 to +7.【wiki】

这是另外一套编码系统,正数也是最高位为0,其他位表示数值,最大就是其他位全为1。负数的表示直接对正数取反。所以这里会出现+0和-0的概念,如下编码图

三、RFC1071文档

直接看到

To generate a checksum, the checksum field itself is cleared,the 16-bit 1’s complement sum is computed over the octets concerned, and the 1’s complement of this sum is placed in thechecksum field.

首先这里的校验法是1补码系统的,不是计算机使用的2补码系统。

ICMP协议使用的校验算法IP、ICMP、UDP和TCP报文头部都有校验和字段,不过IP、TCP、UDP只针对首部计算校验和,而ICMP对首部和报文数据一起计算校验和。检验和算法可以分成两步来实现。首先在发送端,有以下三步:

1.把校验和字段置为0。

2.对需要校验的数据看成以16bit为单位的数字组成,依次进行二进制求和。

3.将上一步的求和结果取反,存入校验和字段。

其次在接收端,也有相应的三步:

1.对需要校验的数据看成以16bit为单位的数字组成,依次进行二进制求和,包括校验和字段。

2.将上一步的求和结果取反。

3.判断最终结果是否为0。如果为0,说明校验和正确。如果不为0,则协议栈会丢掉接收到的数据。

四、CRC

在FPGA上写以太网帧数据时,校验还用到CRC,是不是以太网每层使用的校验算法不一样呢?

先看看以太网帧的数据格式

看看维基大神对FCS的解释

Frame check sequence

The frame check sequence (FCS) is a four-octet cyclic redundancy check (CRC) that allows detection of corrupted data within the entire frame as received on the receiver side. The FCS value is computed as a function of the protected MAC frame fields: source and destination address, length/type field, MAC client data and padding (that is, all fields except the FCS).

Running the CRC algorithm over the received frame data including the CRC code will always result in a zero value for error-free received data, because the CRC is a remainder of the data divided by the polynomial. However, this technique can result in “false negative”, where a data with trailing zeroes will also result in the same zero remainder. To avoid this scenario, the FCS is complemented (reversed for each bit) by the sender before it is attached to the end of the payload data. This way, the algorithm result will always be a magic number or CRC32 residue of 0xC704DD7B when data has been received correctly. This allows for receiving a frame and validating the FCS without knowing where the FCS field actually starts.

可知,这里指定的校验算法就是CRC32,并且校验数据不包括FCS本身。所以来看看CRC32是个什么鬼。

维基的两篇关于crc的介绍

https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Introduction

https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks

国外的crc学习网站

http://www.repairfaq.org/filipg/LINK/F_crc_v31.html

CRC,称为冗余校验的基本思想,就是把任何信息都看作体积庞大的二进制数,为了用固定位来表示校验码(便于统一),就提出一个多项式除数的概念,如果一个冗余的多项式去除以一个固定的多项式,将余数作为校验码使用,就可以实现数据的校验。而除法的本质就是相减,而在二进制中为了减少除法的计算量,采用XOR来替代除法。

例如,要传输信息十进制219,将其转换为二进制11011011b,

规定用于校验的多项式为1010;发生XOR为

因为余数一定比除数至少少一位,所以取011作为校验码,这发送数据为2193.接收方同样用219除1010,如果余数相同,则表示数据正确。

五、为什么在网络传输中校验码需要,不同的算法

在ICMP校验中使用的是checksum的校验,在以太网帧最后使用的是CRC校验,比如在其他TCP包头校验码又是怎样的呢。

tcp/ip协议中规定了IP、ICMP、UDP和TCP报文头部都有校验和字段,并且都是基于checksum的算法。但是也有不一样,

【以下总结来源于网络】

(1)IP校验和:

IP数据报的校验和只检验IP数据报的首部。

(2)UDP校验和:

UDP数据报计算校验和的方法和IP数据报校验和的方法相似,但是UDP的校验和是将首部和数据部分一起都校验。

并且在计算UDP校验和之前需要封装一个伪首部,伪首部结构如下(具体结构定义见后面代码部分):

源IP地址 | 目的IP地址 | 全 0 | 协 议 | UDP长度

(3)TCP校验和:

TCP 的校验和计算方法同UDP一样,同样要加上一个伪头部,区别是伪头部的协议码是0x06,长度是整个TCP报文的长度(包含TCP头部)。

(4)ICMP校验和:

ICMP校验和的计算方法一样,只不过只是对ICMP包整个进行校验和,没有伪头部,也不包括IP包头部。

总结如下: 计算IP数据报和ICMP的校验和时不需要封装伪首部,他俩不同的是IP数据报只检验IP数据报的首部,而ICMP数据报校验包括ICMP头部和数据部分(整个ICMP长度),TCP和UDP的校验方法和IP、ICMP校验方法一样,但是TCP和UDP校验之前需要封装伪首部。还有一个需要注意的是校验的顺序是从上(层)到下(层),如校验ICMP时,先校验ICMP后校验IP(ICMP数据包结构=ether + IP + ICMP), 并且校验之前需要先将校验和的值初始化为0.

也就是说只有以太网使用CRC,其他包头或者数据比较少时采用checksum的算法。

暂时没想到更本质缘由,但一种解释就是,因为CRC本身就是对数据量大的校验,求和(和的容量只有16bit)对于数据量小的校验,

六、完成crc和checksum的实现

首先c实现

checksum就以ICPM为背景。看看ICMP的用于信息回显的数据格式:

Information Request or Information Reply Message

代码为

#include<stdio.h>
struct timeval
{
    long int tv_sec;
    long int tv_usec;
};
struct icmp{
    unsigned char type;
    unsigned char code;
    unsigned short checksum;
    unsigned short id;
    unsigned short num;
    struct timeval t;
};
unsigned short icmp_checksum(unsigned short* s,int len)
{
    unsigned int sum=0;
    unsigned short check;
    int cnt=len>>1;  //cnt is size of 16bit
    while(cnt--)
    {
        sum+=*s++;
    }
    if((len&0x1)==0x1)
        sum+=*(unsigned char*)s;
    while((sum>>16)!=0)
        sum=(sum&0xffff)+(sum>>16);
    return ~check=sum&0xffff;
}
int main()
{
    struct icmp i;
    i.type=8;
    i.code=0;
    i.checksum=0;
    i.id=10;
    i.num=20;
    i.t.tv_sec=100;
    i.t.tv_usec=200;
    i.checksum=icmp_checksum(&i,sizeof(i));
    printf("checksum is %x\n",i.checksum);
    return 0;
}
时间: 2024-10-10 15:56:15

关于校验算法的学习(学习以太网时遇到的)的相关文章

【算法导论】学习笔记——第6章 堆排序

堆这个数据结构应用非常广泛,数字图像处理的算法里也见过.似乎记得以前老师上课说需要用树结构实现堆排序,看了一下算法导论才明白其精髓.堆虽然是一棵树,但显然没必要非得用树结构实现堆排序.堆排序的性质很好,算法时间复杂度为O(nlgn). 1. 堆排序的简要说明.二叉堆可以分为两种形式:最大堆和最小堆.在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] >= A[i]:在最小堆中,最小堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] <= A[

常用校验码(奇偶校验,海明校验,CRC)学习总结

常用校验码(奇偶校验,海明校验,CRC)学习总结 一.为什么要有校验码? 因为在数据存取和传送的过程中,由于元器件或者噪音的干扰等原因会出现错误,这个时候我们就需要采取相应的措施,发现并纠正错误,对于错误的检测和校正,大多采取"冗余校验"的思想,即除原数据外,额外增加若干位编码,这些新增的代码称为校验位. 二.数据是如何校验的? 输入的数据m经过f得到p校验位. 数据m和校验位一起通过存储器或传输线路,分别得到m'和p',这两者可能和m,f相同,也可能由于传输储存发生问题而不同. 由数

Netflix工程总监眼中的分类算法:深度学习优先级最低

Netflix工程总监眼中的分类算法:深度学习优先级最低 摘要:不同分类算法的优势是什么?Netflix公司工程总监Xavier Amatriain根据奥卡姆剃刀原理依次推荐了逻辑回归.SVM.决策树集成和深度学习,并谈了他的不同认识.他并不推荐深度学习为通用的分类技术. [编者按]针对Quora上的一个老问题:不同分类算法的优势是什么?Netflix公司工程总监Xavier Amatriain近日给出新的解答,他根据奥卡姆剃刀原理依次推荐了逻辑回归.SVM.决策树集成和深度学习,并谈了他的不同

Python神经网络算法与深度学习视频教程人工智能算法机器学习实战视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

【机器学习算法应用和学习_2_理论篇】2.2 M_分类_逻辑回归

一.原理阐述 算法类型:监督学习_分类算法 输入:数值型或标称型(标称型需要独热编码) V1.0 用回归方式解决二分类问题,通过引入一个Sigmoid函数将中间y值映射到实际二分类的y值上. 二.算法选择 三.算法过程 1.Sigmoid函数是一个x值域是(-∞,+∞),y值域是(0,1)的单调递增函数: 2.预测y值>0.5为1类,<0.5为0类,y值也可以解释为为1和0类的概率: 3.同样使用“最小二乘”概念,求得最佳方程,得到目标函数: 4.要使得目标函数达到最小,需要采用一种称为“梯度

关于在学习python爬虫时的学习记录

最近学习python3爬虫,看的是这位博主的博客,不得不说,是真的厉害,通俗易懂^?_?^ 我要学习的还有很多-从基本的python知识,我就被难倒了- 哎,记录下我的盲点- 花了近一个钟头测试出来的结果. 在爬取相关的html时,text ≠ text[0] 后者是正确的.我一直以为不加的效果也是一样的结果,在我理解看来就是从头开始的,即从0到尾的所有相关的内容,实际上我的理解与相关的python基础不谋而和,可能是爬虫就需要如此的?我就默认好了- 在python中的方法后面的()是不可省去的

Python3入门机器学习经典算法与应用学习 资源

 Python3入门机器学习经典算法与应用学习 资源 datasets可以用来加载真实数据进行模型训练的测试 import sklearn.datasetsdatasets.load_iris() # 用于加载鸢尾花数据集datasets.load_digits() # 用于加载手写识别的数据集datasets.load_boston() #  用于加载波士顿房价的数据集fetch_mldata用于加载MNIST数据集from sklearn.datasets import fetch_mlda

Dijkstra算法——《算法导论》学习心得(十三)

这两天在做一个项目,关于北京市出租车的,然后用到了Dijkstra算法,所以这篇文章就先写Dijkstra算法了.在大二下的时候学了数据结构,书里面也讲了Dijkstra算法,但是当时怎么也没理解,结果考试的时候就考了,哎蛋疼!现在用到了,又得硬着头皮去学,结果很快弄明白了,只是在写代码时出了一些很低级的错误,调Bug用了不少时间.最后总结只能说:不是你不会,而是没到你非会不可的地步!在这篇文章里我就用实际的项目给大家讲Dijkstra算法. 背景: 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉

传输数据校验算法研究

 今天简单介绍一些传输数据校验的方法,就昨天整理的资料和就我的理解写的Demo做个总结!希望大家多多指教! 定义 通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值.接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,说明数据是完整的. 实际应用 防止自己的程序被篡改. 有些可执行程序,当被改了资源时再运行会有文件已损坏的提示,这就是使用了数据校验.本例是用md5做为数据校验的算法.当然你可以使用个性化的 比如des作为数字签名,那样安全性更高. 校验方法