在平常生活或工做中,咱们在判断与对方网络是否畅通,使用的最多的莫过于 ping
命令了。面试
“那你知道 ping
是如何工做的吗?” —— 来自小林的灵魂拷问缓存
可能有的小伙伴奇怪的问:“我虽然不明白它的工做,但 ping 我也用的贼 6 啊!”bash
你用的是 6 ,但你在面试官面前,你就 6 不起来了,毕竟他们也爱问。网络
因此,咱们要抱有「知其然,知其因此然」的态度,这样就能避免面试过程当中,出门右拐的状况了。app
不知道的小伙伴也不要紧,今天咱们就来搞定它,搞懂它。消除本次的问号,让问号少一点。工具
ping 是基于 ICMP
协议工做的,因此要明白 ping 的工做,首先咱们先来熟悉 ICMP 协议。大数据
ICMP 是什么?spa
ICMP 全称是 Internet Control Message Protocol,也就是互联网控制报文协议。操作系统
里面有个关键词 —— 控制,如何控制的呢?计算机网络
网络包在复杂的网络传输环境里,经常会遇到各类问题。当遇到问题的时候,总不能死的不明不白,没头没脑的做风不是计算机网络的风格。因此须要传出消息,报告遇到了什么问题,这样才能够调整传输策略,以此来控制整个局面。
ICMP 功能都有啥?
ICMP
主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程当中 IP 包被废弃的缘由和改善网络设置等。
在 IP
通讯中若是某个 IP
包由于某种缘由未能达到目标地址,那么这个具体的缘由将由 ICMP 负责通知。
如上图例子,主机 A
向主机 B
发送了数据包,因为某种缘由,途中的路由器 2
未能发现主机 B
的存在,这时,路由器 2
就会向主机 A
发送一个 ICMP
目标不可达数据包,说明发往主机 B
的包未能成功。
ICMP 的这种通知消息会使用 IP
进行发送 。
所以,从路由器 2
返回的 ICMP 包会按照往常的路由控制先通过路由器 1
再转发给主机 A
。收到该 ICMP 包的主机 A
则分解 ICMP 的首部和数据域之后得知具体发生问题的缘由。
ICMP 包头格式
ICMP 报文是封装在 IP 包里面,它工做在网络层,是 IP 协议的助手。
ICMP 包头的类型字段,大体能够分为两大类:
回送消息 —— 类型
0
和8
回送消息用于进行通讯的主机或路由器之间,判断所发送的数据包是否已经成功到达对端的一种消息,ping
命令就是利用这个消息实现的。
能够向对端主机发送回送请求的消息(ICMP Echo Request Message
,类型 8
),也能够接收对端主机发回来的回送应答消息(ICMP Echo Reply Message
,类型 0
)。
相比原生的 ICMP,这里多了两个字段:
PID
做为标识符;0
开始,每发送一次新的回送请求就会加 1
, 能够用来确认网络包是否有丢失。在选项数据中,ping
还会存放发送请求的时间值,来计算往返时间,说明路程的长短。
接下来,说明几个经常使用的 ICMP 差错报文的例子:
3
4
5
11
目标不可达消息(Destination Unreachable Message) —— 类型为
3
IP 路由器没法将 IP 数据包发送给目标地址时,会给发送端主机返回一个目标不可达的 ICMP 消息,并在这个消息中显示不可达的具体缘由,缘由记录在 ICMP 包头的代码字段。
由此,根据 ICMP 不可达的具体消息,发送端主机也就能够了解这次发送不可达的具体缘由。
举例 6 种常见的目标不可达类型的代码:
0
1
2
3
4
为了给你们说清楚上面的目标不可达的缘由,小林牺牲本身给你们送 5 次外卖。
为何要送外卖?别问,问就是为 35
岁的老林作准备 …
外卖版本:
小林第一次送外卖时,小区里只有 A 和 B 区两栋楼,但送餐地址写的是 C 区楼,小林表示头上不少问号,压根就没这个地方。
正常版本:
IP 地址是分为网络号和主机号的,因此当路由器中的路由器表匹配不到接收方 IP 的网络号,就经过 ICMP 协议以网络不可达(Network Unreachable
)的缘由告知主机。
自从再也不有网络分类之后,网络不可达也渐渐再也不使用了。
外卖版本:
小林第二次送外卖时,此次小区有 5 层楼高的 C 区楼了,找到地方了,但送餐地址写的是 C 区楼 601 号房 ,说明找不到这个房间。
正常版本:
当路由表中没有该主机的信息,或者该主机没有链接到网络,那么会经过 ICMP 协议以主机不可达(Host Unreachable
)的缘由告知主机。
外卖版本:
小林第三次送外卖时,此次小区有 C 区楼,也有 601 号房,找到地方了,也找到房间了,可是一开门人家是外国人说的是英语,我说的是中文!语言不通,外卖送达失败~
正常版本:
当主机使用 TCP 协议访问对端主机时,能找到对端的主机了,但是对端主机的防火墙已经禁止 TCP 协议访问,那么会经过 ICMP 协议以协议不可达的缘由告知主机。
外卖版本:
小林第四次送外卖时,此次小区有 C 区楼,也有 601 号房,找到地方了,也找到房间了,房间里的人也是说中文的人了,可是人家说他要的不是外卖,而是快递。。。
正常版本:
当主机访问对端主机 8080 端口时,此次能找到对端主机了,防火墙也没有限制,但是发现对端主机没有进程监听 8080 端口,那么会经过 ICMP 协议以端口不可达的缘由告知主机。
外卖版本:
小林第五次送外卖时,此次是个吃播博主点了 100 份外卖,可是吃播博主要求一次性要把所有外卖送达,小林的一台电动车装不下呀,这样就没办法送达了。
正常版本:
发送端主机发送 IP 数据报时,将 IP 首部的分片禁止标志位设置为1
。根据这个标志位,途中的路由器遇到超过 MTU 大小的数据包时,不会进行分片,而是直接抛弃。
随后,经过一个 ICMP 的不可达消息类型,代码为 4 的报文,告知发送端主机。
原点抑制消息(ICMP Source Quench Message) —— 类型
4
在使用低速广域线路的状况下,链接 WAN 的路由器可能会遇到网络拥堵的问题。
ICMP
原点抑制消息的目的就是为了缓和这种拥堵状况。
当路由器向低速线路发送数据时,其发送队列的缓存变为零而没法发送出去时,能够向 IP 包的源地址发送一个 ICMP 原点抑制消息。
收到这个消息的主机借此了解在整个线路的某一处发生了拥堵的状况,从而增大 IP 包的传输间隔,减小网络拥堵的状况。
然而,因为这种 ICMP 可能会引发不公平的网络通讯,通常不被使用。
重定向消息(ICMP Redirect Message) —— 类型
5
若是路由器发现发送端主机使用了「不是最优」的路径发送数据,那么它会返回一个 ICMP 重定向消息给这个主机。
在这个消息中包含了最合适的路由信息和源数据。这主要发生在路由器持有更好的路由信息的状况下。路由器会经过这样的 ICMP 消息告知发送端,让它下次发给另一个路由器。
比如,小林本能够过条马路就能到的地方,但小林不知道,因此绕了一圈才到,后面小林知道后,下次小林就不会那么傻再绕一圈了。
超时消息(ICMP Time Exceeded Message) —— 类型
11
IP 包中有一个字段叫作 TTL
(Time To Live
,生存周期),它的值随着每通过一次路由器就会减 1,直到减到 0 时该 IP 包会被丢弃。
此时,路由器将会发送一个 ICMP 超时消息给发送端主机,并通知该包已被丢弃。
设置 IP 包生存周期的主要目的,是为了在路由控制遇到问题发生循环情况时,避免 IP 包无休止地在网络上被转发。
此外,有时能够用 TTL 控制包的到达范围,例如设置一个较小的 TTL 值。
接下来,咱们重点来看 ping
的发送和接收过程。
同个子网下的主机 A 和 主机 B,主机 A 执行ping
主机 B 后,咱们来看看其间发送了什么?
ping 命令执行的时候,源主机首先会构建一个 ICMP 回送请求消息数据包。
ICMP 数据包内包含多个字段,最重要的是两个:
8
;每发出一个请求数据包,序号会自动加 1
。为了可以计算往返时间 RTT
,它会在报文的数据部分插入发送时间。
而后,由 ICMP 协议将这个数据包连同地址 192.168.1.2 一块儿交给 IP 层。IP 层将以 192.168.1.2 做为目的地址,本机 IP 地址做为源地址,协议字段设置为 1
表示是 ICMP
协议,再加上一些其余控制信息,构建一个 IP
数据包。
接下来,须要加入 MAC
头。若是在本地 ARP 映射表中查找出 IP 地址 192.168.1.2 所对应的 MAC 地址,则能够直接使用;若是没有,则须要发送 ARP
协议查询 MAC 地址,得到 MAC 地址后,由数据链路层构建一个数据帧,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址;还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。
主机 B
收到这个数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,不然就丢弃。
接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。一样,IP 层检查后,将有用的信息提取后交给 ICMP 协议。
主机 B
会构建一个 ICMP 回送响应消息数据包,回送响应数据包的类型字段为 0
,序号为接收到的请求数据包中的序号,而后再发送出去给主机 A。
在规定的时候间内,源主机若是没有接到 ICMP 的应答包,则说明目标主机不可达;若是接收到了 ICMP 回送响应消息,则说明目标主机可达。
此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
针对上面发送的事情,总结成了以下图:
固然这只是最简单的,同一个局域网里面的状况。若是跨网段的话,还会涉及网关的转发、路由器的转发等等。
可是对于 ICMP 的头来说,是没什么影响的。会影响的是根据目标 IP 地址,选择路由的下一跳,还有每通过一个路由器到达一个新的局域网,须要换 MAC 头里面的 MAC 地址。
说了这么多,能够看出 ping 这个程序是使用了 ICMP 里面的 ECHO REQUEST(类型为 8 ) 和 ECHO REPLY (类型为 0)。
有一款充分利用 ICMP 差错报文类型的应用叫作 traceroute
(在UNIX、MacOS中是这个命令,而在Windows中对等的命令叫作 tracert )。
1. traceroute 做用一
traceroute 的第一个做用就是故意设置特殊的 TTL,来追踪去往目的地时沿途通过的路由器。
traceroute 的参数指向某个目的 IP 地址:
traceroute 192.168.1.100
这个做用是如何工做的呢?
它的原理就是利用 IP 包的生存期限 从 1
开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的一种方法。
好比,将 TTL 设置 为 1
,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络包,类型是时间超时。
接下来将 TTL 设置为 2
,第一个路由器过了,遇到第二个路由器也牺牲了,也同时返回了 ICMP 差错报文数据包,如此往复,直到到达目的主机。
这样的过程,traceroute 就能够拿到了全部的路由器 IP。
固然有的路由器根本就不会返回这个 ICMP,因此对于有的公网地址,是看不到中间通过的路由的。
发送方如何知道发出的 UDP 包是否到达了目的主机呢?
traceroute 在发送 UDP
包时,会填入一个不可能的端口号值做为 UDP 目标端口号(大于 3000
)。当目的主机,收到 UDP 包后,会返回 ICMP 差错报文消息,但这个差错报文消息的类型是「端口不可达」。
因此,当差错报文类型是端口不可达时,说明发送方发出的 UDP 包到达了目的主机。
2. traceroute 做用二
traceroute 还有一个做用是故意设置不分片,从而肯定路径的 MTU。
这么作是为了什么?
这样作的目的是为了路径MTU发现。
由于有的时候咱们并不知道路由器的 MTU
大小,以太网的数据链路上的 MTU
一般是 1500
字节,可是非之外网的 MTU
值就不同了,因此咱们要知道 MTU
的大小,从而控制发送的包大小。
它的工做原理以下:
首先在发送端主机发送 IP
数据报时,将 IP
包首部的分片禁止标志位设置为 1。根据这个标志位,途中的路由器不会对大数据包进行分片,而是将包丢弃。
随后,经过一个 ICMP 的不可达消息将数据链路上 MTU 的值一块儿给发送主机,不可达消息的类型为「须要进行分片但设置了不分片位」。
发送主机端每次收到 ICMP 差错报文时就减小包的大小,以此来定位一个合适的 MTU
值,以便能到达目标主机。
[1] 竹下隆史.图解TCP/IP.人民邮电出版社.
[2] 刘超.趣谈网络协议.极客时间.
小林是专为你们图解的工具人,Goodbye,咱们下次见!
读者问:“有个问题就是A的icmp到了B后,B为啥会自动给A一个回执0?这是操做系统的底层设计吗?”
你说的“回执0”是指 ICMP 类型为 0 吗?若是是的话,那么 B 收到 A 的回送请求(类型为8) ICMP 报文,B 主机操做系统协议栈发现是个回送请求 ICMP 报文,那么协议栈就会组装一个回送应答(类型为0)的 IMCP 回应给 A。