ICMP经常被认为是IP层的一个组成部分,它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或者更高层协议(TCP或者UDP)使用,一些ICMP报文把差错报文直接返回给用户进程。

  1. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2332713/1598179820810-86181c8a-bea6-4e58-b440-b9e0acea0762.png#align=left&display=inline&height=225&margin=%5Bobject%20Object%5D&name=image.png&originHeight=450&originWidth=1196&size=44564&status=done&style=none&width=598)

ICMP报文是在太多了,没有意义关注这么多,现在只要关注一下ping和traceroute两个指令就好了

ping,类型:0,代码:0,描述:回显应答,查询报文
Traceroute,类型:0,代码:0,描述:回显应答,差错报文

因为对ICMP差错报文有时候需要做特殊处理,因此我们需要对他们做区分。例如,在对ICMP差错报文进行响应时候,永远不会生成另外一份ICMP差错报文(如果没有这个限制,可能回遇到一个差错产生另外一个差错对情况,而差错再产生差错,这样无休止地循环下去)

Ping

ping这个词源于声纳定位这个操作,目的就是测试另一台主机是否可以到达,该程序发送一份ICMP回显请求报文给主机,并等待返回ICMP回显应答。Ping程序还能测出到这台主机到往返时间,以表明该主机离我们有“多远”。

我们称发送回显请求的ping程序为客户,而称被ping的主机为服务器。大多数的TCP/IP实现都在内核中直接支持ping服务器,这种服务器不是一种用户进程(在内核中处理)。下面是ICMP的回显请求(客户端)和回显应答报文(服务端)的格式:

  1. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2332713/1598195183411-64e8a986-eed3-434b-a071-dd81695b3b68.png#align=left&display=inline&height=231&margin=%5Bobject%20Object%5D&name=image.png&originHeight=462&originWidth=1048&size=37339&status=done&style=none&width=524)<br />我们来ping一下一个经典地址,www.baidu,com, 结果如下图所示:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2332713/1598195988336-6e0df9c8-5292-41f9-a6d7-35a9b2c3834a.png#align=left&display=inline&height=192&margin=%5Bobject%20Object%5D&name=image.png&originHeight=384&originWidth=1288&size=193573&status=done&style=none&width=644)
  1. Unix系统在实现ping程序时是把ICMP报文中的标识符字段设置为发送进程ID号,这样即使在同一个主机上运行了多个ping程序实例,ping程序也可以识别出返回信息。 序列号从0开始,每发送一次新的回显请求就加1。ping程序打印出返回的每个分组的序号,允许我们查看是否有分组丢失,失序或重复
  2. 当返回ICMP回显应答时,要打印出ICMP序列号和TTL的时间,TTL每经过一个路由就会减1
  3. 通过ICMP报文数据中存放发送请求的时间值来计算往返时间。当应答返回时候,用当前时间减去存放在ICMP报文中的时间值,就是往返时间
  4. 我们还可以发现,如果输入命令之后,锅几秒钟之后才会打印IP地址,BNS就是利用这段时间来确定主机域名所对应的IP地址。
  5. 这个ping的程序是由Mike Muuss实现的

Traceroute

尽管不能保证此从源发往目的端的两份连续的IP数据包具有相同的路由,但是大多数情况下是这样的。traceroute程序可以让我们看到IP数据报从一台主机传到另一台主机所经过的路由。

Traceroute程序使用ICMP报文和IP首部中的TTL字段(生存周期)。TTL字段是由发送端初始设置一个8 bit字段,推荐的初始值为64。其操作过程如下:

  1. 发送一份TTL字段为1的IP数据报给目的主机,处理这份数据报的第一个路由器将TTL减1,丢弃该数据报,并发回一份超时ICMP报文,得到第一个路由器的地址
  2. 然后tracetoute程序发送TTL值为2的数据报,这样我们就可以得到第二个路由器地址
  3. 继续这个过程直到该数据报到达目的主机,但是目的主机哪怕接收到TTL值为1的IP数据报,也不会丢弃数据报产生一份超时报文,因为数据报已经到达最终目的地。我们是这么做的,traceroute发送一份UDP数据报给目的主机,但是它选择的是一个不可能的值作为UDP端口号(大于30000)。因此,当该数据报到达的时候,将使目的主机的UDP模块产生一份“端口不可达”错误的ICMP报文。Traceroute程序所要做的就是区分接收到的ICMP报文是超时还是端口不可达,以判定什么结束。

后面有机会还需要看一下ICMP重定向差错报文,ICMP发现报文,ICMP源站抑制差错报文,RIP协议之间的关系等