说明:本文仅供学习交流,不得用于其它目的,转载请标明出处,欢迎转载!
还记得linux网络命令中的ping和traceroute吗?(在windows中对应ping和tracert),这两个命令的底层实现协议就是本文所要提到的ICMP协议,全称为Internet Control Massage Protocal,网际控制报文协议。
我们知道,IP协议是一种不可靠的协议,它不提供差错报告,也不提供连通查询或路由查询,为了使得网络层的协议能够更加高效地完成数据的传送与接收,ICMP协议脱颖而出,充当IP协议的信使,就像元芳与狄仁杰的关系(呵呵,开个小玩笑)。即ICMP协议与IP协议是从主关系,那么他们肯定在同一个地方工作,换句话说ICMP与IP均处于网络层。尽管网络层与数据链路层是挨着的,但是ICMP报文不能直接传递给数据链路层(这是标准的规定,不要问我为什么),既然不能直接传送值数据链路层,那怎么办?还记得IP数据报的格式中有一个协议字段吗?当该字段的值为1时,该IP数据报的数据部分(不包括首部哈)就是ICMP报文,这一事实告诉我们,ICMP报文被封装在IP数据报的内部,IP数据报对ICMP进行了一次包装(通过加入IP首部)并置协议字段为1。既然ICMP被封装成IP数据报的格式了,那么当然可以顺理成章地交给数据链路层了。
注意:IP首部占20B,ICMP首部占8B,1B=8bit
下面就隆重地介绍下ICMP报文。
根据实际的需要(打下手就该多为主子IP思考),ICMP分为差错报文和查询报文,不管你是差错报文还是查询报文,两者都有公共的部分,如下:
上面是ICMP报文的一般格式,不管哪类ICMP报文,这两个性质是不会变的:
1.首部占用的大小永远是4B;
2.首部的第一个部分(4B为一个部分)的内容均为:类型,代码,检验和。
下面大概介绍下这几个属性!
类型:可想而知,决定了ICMP报文分哪些种。其实ICMP的种类特别多,下图给出了了ICMP的类型。
从上图的分类可以看出,ICMP报文根据报文首部中的类型字段分为差错报文和查询报文两大类,再根据首部中的代码字段,将这两大类再细分为各个小类型的ICMP报文。下面就分别就这些报文做一一介绍。
ICMP差错报文
我们知道,IP是一中不提供差错报告的不可靠协议,ICMP则弥补了这一缺陷,但是要注意,ICMP仅仅是发现问题,并不解决问题。也就是说ICMP根据数据报中的源IP地址只是将差错反馈给源端(主机或路由器),不管源端是否收到,也不管源端是否处理该差错。从上图中可以看出,差错主要分为5大类。为了防止差错报文对广播分组响应带来广播风暴,规定这些情况不能产生ICMP差错报文:
I. ICMP差错报文不能产生ICMP差错报文(防止死循环,当然对查询报文不成立);
II. 目的地址是广播地址或多播地址的IP数据报不能产生;
III.IP数据报的非第一个分片不能产生;
IV.源地址是回环地址、广播地址、全0地址的数据报均不能产生。
注意:每个ICMP差错报文的数据部分都包含了IP首部。
源点抑制
由于在IP协议中没有流量控制与拥塞控制,作为小弟的ICMP设计出了ICMP源点抑制报文,当路由器或主机因网络拥塞而丢弃数据报时,它就向该源点发送源点抑制报文,干嘛呢?这是主机对源点的回应:“我的网络出现拥塞,你(源点)发送过来的数据报已被丢弃,请你放慢发送过程,直到拥塞缓解。”。源点收到该ICMP报文后,不断地降低自己的发送速度,直到不再收到更多的源点抑制报文才不再降低。
超时
什么是超时?
CASE 1(对应代码0):还记得吗?每个IP数据报的首部中都有一个TTL字段,用于记录在寻找目的地的过程中所经过的路由器的个数,当TTL变为0时,路由器便将该数据报丢弃并向源点发送一个超时ICMP报文。
CASE 2(对应代码1):如果我们设置了时间限制,要求在规定的时间内把数据报的所有分组都发送到目的主机。第一个分片到达目的主机时,目的主机就启动其计时器。如果在规定时间内,未收到数据报的所有分片,目的主机就将所收到的所有分片全部扔了,并向源点发送一个超时ICMP报文。
重定向
所谓重定向就是重新选择通往目的主机的路由,通常情况下,主机对应的路由表采用的是静态路由协议,而路由器的路由表通常采用的是动态路由协议。所以主机可能把数据发往一个错误的路由器,这时候呢,哪个所谓的错误的路由器为了“告诉”主机,“你发错了,请你改变你的路向(该路向的IP地址记录在ICMP首部的第二个4B处),并更新你的路由表”,这里所谓的“告诉”方式就是通过发送ICMP重定向报文。有趣的是,该路由器可能拜过唐僧为师,它并不忍心将该报文直接抛弃(毕竟人家只是走错了地方,本身并没有什么毛病),而是将其发送到合适的路由器上。
差错报文就先谈那么多吧,等以后遇到什么有趣的再加上。
查询
还记得ping和traceroute吗?这两个的底层机制就是ICMP查询报文的完成。
查询报文都是成对出现的,因为又问必答!
我所知道的ICMP查询报文包括:地址掩码请求与应答(现已过时,被DHCP协议取代了)、路由询问与回答报文(现已过时,被DHCP取代)、信息请求与回答(现已过时,被ARP取代)、时间戳请求与应答、echo(或叫回显)请求与应答。
时间戳请求与应答
首先我看到时间戳,第一感觉就是想告诉你,那个“戳”念chuo,第一声。要求理解这个报文,第一件事就是要明白什么是时间戳!所谓时间戳就是时刻的意思,就是某一时刻,不是某一时段(有没有想到操作系统中的并行与并发的区别,哈哈)。好了,既然已经理解了这个,我们就来说下时间戳请求与应答的ICMP报文的格式吧。
时间是通用时间的格式(以前称为格林威治标准时间),以毫秒为单位,3个时间都占用32位,时间戳不超过24*60*60*1000。
整个过程为:源点先将报文离开它的时间戳记录在请求报文(代码13)中的发起时间戳位置;接着目的主机或路由器接收到该报文后,将接收时间记录在接收时间戳位置;最后,目的主机或路由器在发送应答时填写传送时间戳,填写完后将完整的时间戳应答报文(代码14)发向远端。实际上,大多数的实现都是把后两个时间戳(即接收时间戳和传送时间戳设为相同的值,提供三个字段的原因是可以让发送发分别计算发送请求的时间和发送应答的时间。
很显然,根据上面的过程,我们可以得出下面几个公式:
源点的发送时间S=接收时间戳-发起时间戳
源点接收时间R=分组返回到源点的时间-传送时间戳
(传送时间戳指的是应答方向源点发送回应报文的时刻)
RTT=S+R
回显(echo)请求与应答
回显请求与应答主要是真的网络的诊断,如ping,traceroute,都是基于回显请求与应答的ICMP报文。
一个源点可以向终点发送echo请求报文,终点收到后产生应答报文,并发送给源点。通过该ICMP报文,源点后终点能判断其是否连通,是否可以进行通信。