平常开发中,咱们常常会碰到查询网络是否畅通以及域名对应 IP 地址等小需求,这时候用的最多的应该就是 ping 命令了。 那你知道 ping 命令是怎么工做的吗?今天,咱们就来一块儿认识下 ping 命令及其对应的 ICMP 协议。网络
ICMP 全称 Internet Control Message Protocol,指互联网控制报文协议。3d
网络自己是不可靠的,数据包在传输过程当中,可能会发生不少突发事件并致使数据传输失败。而网络层的 IP 协议是一个无链接的协议,它不会处理网络层的故障,所以,咱们须要其它的协议,在数据包传输出现故障时,能将故障信息传回来,这样才能对应处理相关问题。cdn
就像在电视剧里看到的古代战争同样,打仗的时候须要经过斥候来传递战局状况,进而更好的控制战局。而 ICMP 报文在网络世界中就充当“斥候”这样的角色。blog
ICMP 报文是封装在 IP 包里面的。由于传输指令的时候,确定须要源地址和目标地址。它自己格式很是简单,以下图:事件
ICMP 报文有不少的类型,不一样的类型有不一样的代码,最经常使用的类型是主动请求,代码为 8,主动请求的应答,代码为 0。从大的方面看能够分为 查询报文类型和差错报文类型。路由
咱们常常在电视剧里听到这样的话:来人,前方战事如何?斥候回来没?一有状况,马上通报。开发
相似这种主帅发起,主动查看敌情的状况,就对应着 ICMP的查询报文类型。例如,常见的 ping 命令就是查询报文,是一种主动请求,而且得到主动应答的 ICMP 协议。所以,ping 命令发出的包也是符合 ICMP 协议格式的,只不过它在后面增长了本身的格式。域名
对 ping 的主动请求,进行网络抓包,称为 ICMP ECHO REQUEST。同理,主动请求的回复,称为ICMP ECHO REPLY。比起原生的 ICMP,这里面多了两个字段,一个是标识符,另外一个是序号。这不难理解,大帅派出去两队斥候,一队是找谁要的,一队是侦查战况的,要有个标识才能区分。it
另外一方面,派出去的斥候,都要编个号。若是派出去 10 个,回来 10 个,就说明前方战况不错。若是派出去 10 个,回来 2 个,就说明状况可能不妙。io
在选项数据中,ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。
差错报文主要是用来将发送的出错报文相关信息返回到源设备,以供源设备肯定若是更好的重发失败的数据包。
仍是拿咱们的“大帅”举例。
当主帅正在大账中看地图,思考战事时,外面的小兵忽然喊到:大帅,很差啦,张将军遭遇埋伏,全军覆没了。
这种是异常状况发起的,来报告发生了很差的事情,对应 ICMP 的差错报文。
差错报文有如下经常使用的类型:
第一种状况终点不可达。小兵报告,大帅,送给张将军的粮草没有送到。
那大帅确定会问,为啥没有送到?这就对应 ICMP 中的如下代码了。
具体的场景就像这样:
第二种是源站抑制。也就是让源站放慢发送速度(小兵:大帅,粮草送的太多了吃不完,你能够慢点送)。
第三种是时间超时。也就是超过网络包的生存时间仍是没到目的地(大帅,送粮草的人都把粮食吃完了,还没到地方,已经饿死了)。
第四种是路由重定向。也就是下次发给另外一个路由器(大帅,上次送粮草的人原本只要走大王村,一千米就到了,结果非要绕道张家界,多了五千米,下次记得走大王村)。
差错报文的结构相对复杂一些。除了前面仍是 IP,ICMP 的前 8 个字节不变,后面则跟上出错的那个 IP 包的 IP 头和 IP 正文的前 8 个字节。
并且这类斥候特别尽责,不但字节返回来报信,还把一部分遗物带回来。
接下来,咱们重点来看 ping 命令的发送和接收过程。
假定主机 A 的 IP 地址是 192.168.1.1,主机 B 的 IP 地址是 192.168.1.2,它们都在同一个子网。那么,当在主机 A 上运行“ping 192.168.1.2” 后,会发生什么呢?
主机 B 收到数据帧后,会进行以下步骤:
在规定的时间内,源主机若是没有接到 ICMP 的应答包,则说明目标主机不可达。
若是接收到了应打包,则说明目标主机可达。此时,源主机会检测时间延迟。就是用当前时刻减该数据包从源主机发出去的时刻。
固然,这只是最简单的,同个局域网的状况。若是跨网段的话,还会涉及网关的转发、路由器的转发等。
能够看出,ping 命令是使用了 ICMP 里面的 ECHO REQUEST 和 ECHO REPLY 类型。
那其它类型呢?是否是只有真正遇到错误的时候,才能收到?答案是否认的。有一个 Traceroute 命令,它会使用 ICMP 的规则,故意制造一些可以产生错误的场景。
Traceroute 命令有两个比较经常使用的功能。
第一个功能:
经过设置特殊的 TTL,追踪去往目的地时通过的路由器
Traceroute 的参数执行某个目的 IP 地址,会发送一个 UDP 的数据包。
将 TTL 设置成 1 时,表示这个数据包的 MP 为 1,碰到第一个“拦路虎”(一般是路由器或一个其它类型的关卡)就会阵亡了,而后就会返回一个 ICMP 包,这个包就是 网络差错包,类型是时间超时。
经过差错包,咱们就能获得数据包到第一个关卡时花费的时间及其每一个关卡的 IP 地址(有的主机不会响应 ICMP,因此会出现请求时全是 * 的状况)。
那怎么知道 UDP 有没有到达目的主机呢?Traceroute 程序会发送一份 UDP 数据包给目的主机,但它会选择一个不可能的值做为 UDP 端口号(大于30000)。当该数据报到达目的主机时,因为找不到对应端口号,因此会返回一个“端口不可达”的错误报文。这样,咱们就知道 UDP 是否到达主机了。
第二个功能:
设置数据包不分片,肯定路径的 MTU
发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口的 MTU 相等。若是中间遇到窄的关卡就会被卡主,返回 ICMP 网络差错包,类型是“须要进行分片但设置了不分片”。就这样,每次收到ICMP“不能分片”差错时就减少分组的长度,从而肯定整个路径中的 MTU。
参考: