ping 是基于 ICMP 协议工做的。ICMP全称Internet Control Message Protocol,就是互联网控制报文协议。
ICMP 报文是封装在 IP 包里面的。由于传输指令的时候,确定须要源地址和目标地址。它自己很是简单。
ICMP 报文有不少的类型,不一样的类型有不一样的代码。最经常使用的类型是主动请求为 8,主动请求的应答为 0。网络
经常使用的ping 就是查询报文,是一种主动请求,而且得到主动应答的 ICMP 协议。因此,ping 发的包也是符合 ICMP 协议格式的,只不过它在后面增长了本身的格式。
对 ping 的主动请求,进行网络抓包,称为ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY。比起原生的 ICMP,这里面多了两个字段,一个是标识符(标识是请求仍是回复),另外一个是序号(每一个发出的报文都有序号)。测试
在选项数据中,ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。spa
终点不可达为 3,源抑制为 4,超时为 11,重定向为 5。
差错报文的结构相对复杂一些。除了前面仍是 IP,ICMP 的前 8 字节不变,后面则跟上出错的那个 IP 包的 IP 头和 IP 正文的前 8 个字节。blog
ping 命令执行的时候,源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含多个字段。最重要的是两个,第一个是类型字段,对于请求数据包而言该字段为 8;另一个是顺序号,主要用于区分连续 ping 的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加 1。为了可以计算往返时间 RTT,它会在报文的数据部分插入发送时间。路由
主机 B 会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,而后再发送出去给主机 A。it
在规定的时候间内,源主机若是没有接到 ICMP 的应答包,则说明目标主机不可达;若是接收到了 ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。class
常常会遇到一个问题,若是不在咱们的控制范围内,不少中间设备都是禁止 ping 的,可是ping 不通不表明网络不通。这个时候就要使用 telnet,经过其余协议来测试网络是否通。route
ping 这个程序是使用了 ICMP 里面的 ECHO REQUEST 和 ECHO REPLY 类型。路由器
有一个程序Traceroute,它会使用 ICMP 的规则,故意制造一些可以产生错误的场景。因此,Traceroute 的第一个做用就是故意设置特殊的 TTL,来追踪去往目的地时沿途通过的路由器。互联网
Traceroute 的参数指向某个目的 IP 地址,它会发送一个 UDP 的数据包。将TTL 设置成 1,也就是说一旦遇到一个路由器或者一个关卡,就表示它“牺牲”了。若是中间的路由器不止一个,固然碰到第一个就“牺牲”。因而,返回一个 ICMP 包,也就是网络差错包,类型是时间超时。
接下来,将 TTL 设置为 2。第一关过了,第二关就“牺牲”了,那我就知道第二关有多远。如此反复,直到到达目的主机。这样,Traceroute 就拿到了全部的路由器 IP。固然,有的路由器压根不会回这个 ICMP。这也是 Traceroute 一个公网的地址,看不到中间路由的缘由。
怎么知道 UDP 有没有到达目的主机呢?Traceroute 程序会发送一份 UDP 数据报给目的主机,但它会选择一个不可能的值做为 UDP 端口号(大于 30000)。当该数据报到达时,将使目的主机的 UDP 模块产生一份“端口不可达”错误 ICMP 报文。若是数据报没有到达,则多是超时。
Traceroute 还有一个做用是故意设置不分片,从而肯定路径的 MTU。要作的工做首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。若是中间遇到窄的关口会被卡住,会发送 ICMP 网络差错包,类型为“须要进行分片但设置了不分片位”。其实,这是人家故意的好吧,每次收到 ICMP“不能分片”差错时就减少分组的长度,直到到达目标主机。
ping 使用查询报文,Traceroute 使用差错报文