你知道PING功能是怎么实现的吗
以太网的协议有层,而每层都包含有更多的协议。所谓协议,通俗的讲就是通信双方约定的规则。
今天我们介绍一些一个听起来陌生却有很常用的协议,ICMP协议。
ICMP是(Internet Control Message Protocol)Internet控制报文协议。ICMP协议是一种面向无连接的协议,它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递和网络安全具有极其重要的意义。
ICMP设计的最初目的主要是用于IP层(以太网第三层网络层)的差错报告,一路由器或信宿以一对一的模式向信源报告传输错误的原因。
随着网络的发展,检测和控制能力逐渐被引入到ICMP协议中,使得ICMP协议不仅用于传输差错报告,而且大量用于传输控制报文。
ICMP两级封装,如下图:
ICMP协议与IP协议位于同一层次(IP层),但ICMP报文是封装在IP数据报的数据部分进行传输的。由上图我们可以看出。
TCP/IP协议栈中,ICMP协议位于比IP协议略高的位置。但ICMP不作为单独的独立层次,而只是IP层的一部分。
ICMP协议是IP协议的补充,用于IP层的差错报告,拥塞控制,路径控制以及路由器或主机信息的获取。
ICMP报文由首部和数据段组成。(注:不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理。)
ICMP首部定长为8个字节。前4个字节是通用部分,后4个字节随报文类型的不同有所差异。一般格式如下:
类型(type):8bit,ICMP报文类型。
ICMP报文虽然细分为很多类,但总的来看可分为如图所示的三大类:差错报告,控制报文,和请求应答报文。
代码(code):8bit,报文类型的进一步信息。
由于类型众多,我们以实现PING功能的回应请求与应答报文做出说明。
回应请求与应答报文的目的是对网络进行诊断和测试。请求方(路由器,主机)向某信宿机(主机或路由器)发送一个回应请求,请求的数据区带有发送发给定的数据。
信宿机收到请求以后,根据请求形成回应应答,数据中包含请求所带的数据。
信源机根据应答报文中所带的数据就可以确定两个设备间是否可以正常通信。回应请求与应答不仅可以被用来测试主机或路由器的可达性 ,还可以测试IP协议的工作情况。
如果请求方能够成功收到对请求方的应答,那么不但说明信宿可达,而且说明信源机和信宿机的ICMP协议和IP协议工作正常,同时也说明请求和应答经过的中间路由器能够正常进行路由。
ICMP回应请求与应答报文的格式:
类型“8”,表明回应请求报文,要发送请求报文或者收到了请求报文
类型“0”,表明回应应答报文,收到应答报文或者要发送应答报文
代码:在这种类型中为0;
协议为对标识符和序列号字段进行正式定义,通常标识符和序列号用于匹配请求和应答。标识符一般为发起请求进程的进程ID,回应请求与应答报文的标识符和序列号一致。
标识符和序列号作为首部的其他部分,共占32bit。大部分报文不使用该字段,置0,参数错报告会用到其中的一个字节做指针,请求应答报文对利用该4个字节匹配请求与应答报文。
在使用请求与应答报文时(PING功能)时,可将标识符和序列号随机定义,比如在请求报文中将标识符两个字节定义为0x1234,将序列号两个字节定义为0x4321,那么在接收到应答报文时,相应的两个字节数据是一致的,如果不一致说明应答出错。
校验和(checksum):16bit,ICMP整个报文的校验和。
数据部分:差错报告时,携带原始出错数据的首部和数据的前8个字节,包括了该数据包的关键信息(详见ICMP协议)。
请求与应答报文中,携带请求与应答相关的额外信息。通常由发送方指定数据,接收方原样返回。
计算校验和:
当发送请求时,应将校验和16bit先置0,计算所有数据的校验和之后将16位校验和放到报文的校验和字段。
当发送应答时,应将校验和16bit先置0,将类型改为应答,计算所有数据的校验和之后将16位校验和放到报文的校验和字段。
校验校验和:
当收到请求或应答时,与计算校验和一样重新算一遍,如果全为1,说明正确。
ICMP具体算法:(与IP校验和稍有不同)
为了计算一份数据报的ICMP检验和,首先把检验和字段置为0。然后,对整个ICMP报文中每个16 bit进行二进制反码求和(整个报文看成是由一串16 bit的字组成),结果存在检验和字段中。当收到一份ICMP数据报后,同样对数据报文中每个16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果数据报在传输过程中没有发生任何差错,那么接收方计算的结果应该为全0。另外ICMP数据报的长度可以为奇数字节,所以在计算校验和时需要在最后增加填充字节0(填充字节只是为了计算校验和,可以不被传送)。
1、把ICMP报文二进制数据以2字节为单位累加起来(以16位计算)。存入32位的变量reg中。
2、若ICMP报文为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节这个2字节数据的低字节为0,继续累加。
3、校验和是以16位为单位进行求和计算的,放到32位的变量reg中存储,取reg高16位于低16位继续累加,此时是将之前的进位进行累加。
4、继续去reg高16位和低16位进行累加,这步主要是考虑到上一步加法有进位。
5、对上述结果进行取反,去低16位输出即可作为检验和。
由于上述计算校验和时将进位也计算在内,所以校验校验和时得到的结果应该是0。
举个简单例子,发送端发送A和B数据以及校验和E。
A=1010_1010_1010_1010
B=1001_1001_1001_1001
计算A和B的和:(相加)
C=1_0100_0100_0100_0011
计算进位(累加进位,高16位)
D=0100_0100_0100_0100
计算校验和(按位取反)
E=1011_1011_1011_1011
接收端接收到A和B以及校验和之后,验证校验和:
A=1010_1010_1010_1010
B=1001_1001_1001_1001
E=1011_1011_1011_1011
计算A、B、E的和:
F=1_1111_1111_1111_1110
继续累加进位,高16位为进位
G=1111_1111_1111_1111
计算校验和(按位取反)
H=0000_0000_0000_0000
可以看到,ICMP在计算校验和的过程中将进位加入,所以最终收到数据报文校验校验和的时候,得到的校验和(16位)为0,要想得到16位全为1的结果,对校验校验和按位取反就可以了。
注:在上述算法中,先相加后取反与先取反后相加得到的结果是一样的。
版权所有权归卿萃科技,转载请注明出处
作者:卿萃科技ALIFPGA
原文地址:卿萃科技FPGA极客空间 微信公众号
扫描二维码关注卿萃科技FPGA极客空间