ICMP、IGMP、UDP、TCP 协议是基于 IP 协议的。 ICMP 协议是封装在 IP 协议里的。 完整的 ICMP 报文的格式是这样的:
| 以太网头部 | IP 首部 | ICMP 报文 | CRC |
ICMP 协议的强大之处在于它的丰富的报文类型。可以简单简单的分为两种报文,一种是查询报文,比如ping 程序使用的回显应答;另一种是差错报文,比如主机不可达。
ICMP 报文的前32位 : | 8位类型 | 8位代码 | 16位校验和 |
类型和代码的不同组合,就可以整出来各种各样的 ICMP 报文。
比如 0:0 表示回显应答;8:0 表示请求回显。
不同的报文类型会有不同的处理方式,一般差错报文会始终包含 IP 的首部和产生 ICMP 差错报文的 IP 数据包的前8个字节(TCP/UDP 报文的前8个字节是源/目的端口号,ICMP 报文的前8个字节一般包含了大部分的元数据)
下面看一下 ping 程序。
大多数的TCP/IP 实现都在内核中直接支持 Ping 服务器。
报文格式为:
| 类型-8位 | 代码-0位| 检验和-16位 |
| 标识符-16位 | 序号-16位 |
| 选项数据 |
Unix 系统在实现 ping 程序的时候是吧 ICMP 报文中的标识符字段置成发送进程的 ID 号。这样即使在同一台主机上同时运行多个 ping 程序实例。ping 程序也能识别出返回的信息。
序列号从0开始,每发送一次新的回显请求,就加一。
ping 程序每秒发送一个回显请求,并打印出返回的每一个回显应答。
➜ ~ >ping www.baidu.com
PING www.a.shifen.com (220.181.112.244): 56 data bytes
64 bytes from 220.181.112.244: icmp_seq=0 ttl=54 time=5.040 ms
64 bytes from 220.181.112.244: icmp_seq=1 ttl=54 time=9.202 ms
64 bytes from 220.181.112.244: icmp_seq=2 ttl=54 time=10.052 ms
ping 程序通过在 ICMP 报文中存放发送请求的时间来计算往返时间。当应答返回时,使用当前的时间减去存放在 ICMP 报文中的时间值,即是往返时间。
另外,ping 程序的-R 选项可以记录路由信息,利用了 IP 数据包的 RR 选项。当 ICMP 报文经过每一个路由的时候,路由会自动把自己的 IP 地址放到ICMP报文的最后。当ICMP报文到达回显服务器的时候,回显服务器负责包已有的路由地址拷贝到ICMP应答报文中。当 ICMP 应答报文返回到请求主机时,就有了完整的IP 地址清单。但是 RR 选项是可选功能,可能路由或者主机没有实现这个功能的话,那么这个地址清单就不准了。