在[RFC 792]中指定了ICMP (Internet Control Message Protocol)协议,**用于主机和路由器之间的网络层信息通信**。ICMP最典型的用途是**错误报告(error reporting)**。例如,在运行HTTP会话时,您可能会遇到一条错误报文,例如“目的网络不可达(Destination network unreachable)”。此报文起源于ICMP。在某些情况下,IP路由器无法找到HTTP请求中指定的主机路径。路由器创建并发送一个ICMP报文到您的主机,指示这个错误。<br />**ICMP通常被认为是IP的一部分,但从架构上讲,它位于IP之上,因为ICMP报文是在IP数据报中携带的。**也就是说,ICMP报文作为IP负载携带,就像TCP或UDP段作为IP负载携带一样。类似地,当主机接收到一个IP数据报,其中ICMP被指定为上层协议(上层协议编号为1),它将数据报的内容解复用到ICMP,就像它将数据报的内容解复用到TCP或UDP一样。<br />ICMP报文有一个类型(type)和一个代码(code)字段,并包含导致生成ICMP报文的IP数据报的首部和前8个字节(以便发送方可以确定导致错误的数据报)。选定的ICMP报文类型如图5.19所示。注意,ICMP报文不仅用于发送错误情况。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12377925/1637761397849-cba643a0-15b5-457a-8422-9780f9401de1.png#clientId=u8dc9391b-87fa-4&from=paste&height=611&id=u2d173d73&margin=%5Bobject%20Object%5D&name=image.png&originHeight=611&originWidth=842&originalType=binary&ratio=1&size=63790&status=done&style=none&taskId=ud87ea5d2-0848-4989-bb9e-24adbd2ebbe&width=842)<br />**Figure 5.19 ♦ ICMP message types**<br />**图5.19 ♦ ICMP报文类型**<br />众所周知的ping程序向指定的主机发送ICMP类型8代码0报文。目标主机看到回送请求后,发送一个类型为0码0的ICMP回送应答。大多数TCP/IP实现都直接支持操作系统中的ping服务器(server);也就是说,服务器(server)不是一个进程。[Stevens 1990]的第11章提供了ping客户端程序的源代码。请注意,客户端程序需要能够指示操作系统生成类型为8代码0的ICMP报文。<br />另一个有趣的ICMP报文是源抑制报文(source quench message)。这个报文在实践中很少使用。它最初的目的是执行拥塞控制——允许一个拥塞路由器向一个主机发送ICMP源终止报文,以迫使该主机降低它的传输速率。我们在第三章已经看到TCP有自己的拥塞控制机制,它在传输层运行,并且显式拥塞通知位可以被网络后端设备使用来发出拥塞信号。<br />在第一章中,我们介绍了Traceroute程序,它允许我们跟踪从一个主机到世界上任何其他主机的路由。有趣的是,Traceroute是通过ICMP消息实现的。为了确定源和目的之间路由器的名称和地址,源端的Traceroute向目的端发送一系列普通的IP数据报。这些数据报中的每一个都携带一个带有不太可能的UDP端口号的UDP段。这些数据报中的第一个TTL为1,第二个TTL为2,第三个TTL为3,以此类推。源还为每个数据报启动计时器。当第n个数据报到达第n个路由器时,第n个路由器发现该数据报的TTL刚刚过期。根据IP协议的规则,路由器丢弃该数据报,并向源发送ICMP警告消息(type 11 code 0),该警告消息包括路由器的名称和IP地址。当此ICMP报文返回到源端时,源端从定时器中获取往返时间,并从ICMP报文中获取第n个路由器的名称和IP地址。<br />如何Traceroute源知道何时停止发送UDP段?回忆一下,源为它发送的每个数据报增加TTL字段。因此,其中一个数据报最终将到达目标主机。因为这个数据报包含一个带有不太可能的端口号的UDP段,所以目标主机将一个端口不可达的ICMP消息(类型3代码3)发送回源端。当源主机收到这个特定的ICMP消息时,它知道它不需要发送额外的探测包。(标准的Traceroute程序实际上发送三个具有相同TTL的数据包;因此,Traceroute输出为每个TTL提供三个结果。)<br />通过这种方式,源主机可以了解到位于它和目的主机之间的路由器的数量和标识,以及两台主机之间的往返时间。请注意,Traceroute客户端程序必须能够指示操作系统生成具有特定TTL值的UDP数据报,并且必须能够在ICMP消息到达时由其操作系统通知。现在您已经了解了Traceroute的工作原理,您可能想要返回并对它进行更多的操作。<br />RFC 4443中已经为IPv6定义了一个新的ICMP版本。除了重新组织现有的ICMP类型和代码定义外,ICMPv6还添加了新的IPv6功能所需的新类型和代码。这些错误包括“包太大”类型和“无法识别的IPv6选项”错误代码。