ping通常作为"测试对方主机是否可达"的手段,而实际上这种手段有很多种,依据不同的协议来实现,本质上都是发送一个数据,然后根据对方的回应来分析网络状态。ping程序只是其中常用的一种,依靠ICMP实现。

1 ICMP(Internet Controll Message Protocol)

ICMP是网络控制协议,按功能来说它是属于网络层协议的一部分,但是格式上跟传输层协议类似,都是封装在IP数据包里面。

基本格式如下

ICMP消息封装格式

其中类型字段是大类,代码字段是大类中的子类,具体可以参见rfc792

ping的请求类型是8,代码是0,回应类型是0,代码是0

2 ping 程序

ping程序的原理就是发送一个ICMP echo request 请求(type=8,code=0),然后接收方回应echo reply,内容一样(type=8,code=0)

用于ping的ICMP消息在基本格式的基础上,增加了两个字段,identifiersequence number,两个字段都是用来识别一个消息的,因为一个机器可以同时发送多个消息,一个服务器也可以同时接收多个消息,这两个字段的设置在不同的实现下不一定相同。

ping的ICMP消息格式

在linux系统中,identifier通常使用进程ID,sequence number则每次都从1开始递增,一个常见的输出如下:

linux下ping的输出

输出信息中,from后面的IP是服务端IP地址,icmp_seq就是sequence number,ttl是IP头部中的信息(TTL,time to tive),time表示rtt。

第1行中56(84)分别表示:发送的数据是56B,而IP数据包的大小是84B(64B的ICMP消息+20B的IP头部)。

下面每一行的64bytes表示ICMP消息大小是64B(56+8B的头部)。

rtt则是通过在ICMP消息的可选项中携带发送时的客户端时间信息,然后在接收到服务器端的回应时(服务器回应收到的相同内容),用当前的系统时间减去发送时的时间来计算差值。

3 ping的局限性

ping程序依赖ICMP消息来分析网络状态,一个服务器能不能ping通,不能说明它的其它服务是否可用,可能出现下面的情况:

  • 不能Ping通但能提供服务:服务器端拒绝ping请求(比如设置了防火墙规则防止大量的ping占用带宽),但是其它端口的服务正常运行。可以通过抓包工具随机选取一个包来测试,ping相应的IP,很可能就不能ping通,现在服务器拒绝ping请求是很常见的。
  • 能ping通但不能提供服务:服务器端虽然回应了ping请求,但是相应的端口服务不能正常运行,这种情况并不能通过ping测试来正确反映特殊端口的状态,需要针对具体的端口服务有针对性的测试。

虽然ping不能反映特殊端口的状态,但是可以用来辅助测试。至少在能ping通的情况下,我们认为客户端到服务器的网络是可以到达的,如果此时相应的服务不能运行,那么有可能是防火墙规则或者应用层的问题。