7.2 Ping程序
我们称发送回显请求的 p i n g程序为客户,而称被 p i n g的主机为服务器。大多数的 T C P / I P实现都在内核中直接支持 P i n g服务器—这种服务器不是一个用户进程(在第 6章中描述的两种I C M P查询服务,地址掩码和时间戳请求,也都是直接在内核中进行处理的)。
I C M P回显请求和回显应答报文如图 7 - 1所示。
对于其他类型的I C M P查询报文,服务器必须响应标识符和序列号字段。另外,客户发送的选项数据必须回显,假设客户对这些信息都会感兴趣。
U n i x系统在实现p i n g程序时是把I C M P报文中的标识符字段置成发送进程的 I D号。这样即使在同一台主机上同时运行了多个 p i n g程序实例,p i n g程序也可以识别出返回的信息。序列号从0开始,每发送一次新的回显请求就加 1。p i n g程序打印出返回的每个分组的序列号,允许我们查看是否有分组丢失、失序或重复。 I P是一种最好的数据报传递服务,因此这三个条件都有可能发生。
旧版本的p i n g程序曾经以这种模式运行,即每秒发送一个回显请求,并打印出返回的每个回显应答。但是,新版本的实现需要加上- s选项才能以这种模式运行。默认情况下,新版本的p i n g程序只发送一个回显请求。如果收到回显应答,则输出“ host is alive”;否则,在2 0秒内没有收到应答就输出“ no answer(没有回答)”。
7.2.1 LAN输出
在局域网上运行p i n g程序的结果输出一般有如下格式:
当返回I C M P回显应答时,要打印出序列号和 T T L,并计算往返时间( T T L位于I P首部中的生存时间字段。当前的 B S D系统中的 p i n g程序每次收到回显应答时都打印出收到的 T T L—有些系统并不这样做。我们将在第 8章中通过t r a c e r o u t e程序来介绍T T L的用法)。
从上面的输出中可以看出,回显应答是以发送的次序返回的( 0,1,2等)。p i n g程序通过在I C M P报文数据中存放发送请求的时间值来计算往返时间。当应答返回时,用当前时间减去存放在 I C M P报文中的时间值,即是往返时间。注意,在发送端 b s d i上,往返时间的计算结果都为 0 ms。这是因为程序使用的计时器分辨率低的原因。 B S D / 3 8 6版本0 . 9 . 4系统只能提供10 ms级的计时器(在附录B中有更详细的介绍)。在后面的章节中,当我们在具有较高分辨率计时器的系统上( S u n)查看t c p d u m p输出时会发现,I C M P回显请求和回显应答的时间差在4 ms以下。
输出的第一行包括目的主机的 I P地址,尽管指定的是它的名字( s v r 4)。这说明名字已经经过解析器被转换成 I P地址了。我们将在第 1 4章介绍解析器和 D N S。现在,我们发现,如果敲入p i n g命令,几秒钟过后会在第 1行打印出I P地址,D N S就是利用这段时间来确定主机名所对应的I P地址。
本例中的t c p d u m p输出如图7 - 2所示。从发送回显请求到收到回显应答,时间间隔始终为 3.7 ms。还可以看到,回显请求大约每隔1秒钟发送一次。
通常,第1个往返时间值要比其他的大。这是由于目的端的硬件地址不在 A R P高速缓存中
的缘故。正如我们在第 4章中看到的那样,在发送第一个回显请求之前要发送一个 A R P请求并接收A R P应答,这需要花费几毫秒的时间。下面的例子说明了这一点:
第1个RT T中多出的3 ms很可能就是因为发送A R P请求和接收A R P应答所花费的时间。这个例子运行在s u n主机上,它提供的是具有微秒级分辨率的计时器,但是 p i n g程序只能打印出毫秒级的往返时间。在前面运行于 BSD/386 0.9.4版上的例子中,打印出来的往返时间值为0 ms,这是因为计时器只能提供 1 0 m s的误差。下面的例子是BSD/386 1.0版的输出,它提供的计时器也具有微秒级的分辨率,因此, p i n g程序的输出结果也具有较高的分辨率。
7.2.2 WAN输出
在一个广域网上,结果会有很大的不同。下面的例子是在某个工作日的下午即 I n t e r n e t具有正常通信量时的运行结果:
这里,序列号为1、2、3、4、6、1 0、11、1 2和1 3的回显请求或回显应答在某个地方丢失了。另外,我们注意到往返时间发生了很大的变化(像 5 2 %这样高的分组丢失率是不正常的。
即使是在工作日的下午,对于 I n t e r n e t来说也是不正常的)。通过广域网还有可能看到重复的分组(即相同序列号的分组被打印两次或更多次),失序的分组(序列号为N 1的分组在序列号为N的分组之前被打印)。
7.2.3 线路SLIP链接
让我们再来看看 S L I P链路上的往返时间,因为它们经常运行于低速的异步方式,如 9 6 0 0 b / s或更低。回想我们在 2 . 1 0节计算的串行线路吞吐量。针对这个例子,我们把主机 b s d i和s l i p之间的S L I P链路传输速率设置为1200 b/s。
下面我们可以来估计往返时间。首先,从前面的 P i n g程序输出例子中可以注意到,默认情况下发送的I C M P报文有5 6个字节。再加上2 0个字节的I P首部和8个字节的I C M P首部,I P数据报的总长度为 8 4字节(我们可以运行 t c p d u m p-e命令查看以太网数据帧来验证这一点)。
另外,从2 . 4节可以知道,至少要增加两个额外的字节:在数据报的开始和结尾加上 E N D字符。此外,S L I P帧还有可能再增加一些字节,但这取决于数据报中每个字节的值。对于 1200 b/s这个速率来说,由于每个字节含有 8 bit数据、1 bit起始位和1 bit结束位,因此传输速率是每秒1 2 0个字节,或者说每个字节 8.33 ms。所以我们可以估计需要 1 4 3 3(8 6×8 . 3 3×2)m s(乘2 是因为我们计算的是往返时间)。
下面的输出证实了我们的计算:
(对于S V R 4来说,如果每秒钟发送一次请求则必须带- s选项)。往返时间大约是 1 . 5秒,但是程序仍然每间隔 1秒钟发送一次 I C M P回显请求。这说明在第 1个回显应答返回之前(1 . 4 8 0秒时刻)就已经发送了两次回显请求(分别在 0秒和1秒时刻)。这就是为什么总结行指出丢失了一个分组。实际上分组并未丢失,很可能仍然在返回的途中。我们在第8章讨论t r a c e r o u t e程序时将回头再讨论这种低速的 S L I P链路。
7.2.4 拨号SLIP链路
对于拔号 S L I P链路来说,情况有些变化,因为在链路的两端增加了调制解调器。用在s u n和n e t b系统之间的调制解调器提供的是 V. 3 2调制方式( 9600 b/s)、V. 4 2错误控制方式(也称作L A P - M)以及V. 4 2 b i s数据压缩方式。这表明我们针对线路链路参数进行的简单计算不再准确了。
很多因素都有可能影响。调制解调器带来了时延。随着数据的压缩,分组长度可能会减小,但是由于使用了错误控制协议,分组长度又可能会增加。另外,接收端的调制解调器只能在验证了循环检验字符(检验和)后才能释放收到的数据。最后,我们还要处理每一端的计算机异步串行接口,许多操作系统只能在固定的时间间隔内,或者收到若干字符后才去读这些接口。
作为一个例子,我们在s u n主机上p i n g主机g e m i n i,输出结果如下:
注意,第1个RT T不是10 ms的整数倍,但是其他行都是 10 ms的整数倍。如果我们运行该程序若干次,发现每次结果都是这样(这并不是由 s u n主机上的时钟分辨率造成的结果,因为根据附录B中的测试结果可以知道它的时钟能提供毫秒级的分辨率)。
另外还要注意,第1个RT T要比其他的大,而且依次递减,然后徘徊在 2 8 0~300 ms之间。我们让它运行1 ~ 2分钟,RT T一直处于这个范围,不会低于 260 ms。如果我们以9600 b/s的速率计算RT T(习题7 . 2),那么观察到的值应该大约是估计值的 1 . 5倍。
如果运行p i n g程序6 0秒钟并计算观察到的 RT T的平均值,我们发现在 V. 4 2和V. 4 2 b i s模式下平均值为277 ms(这比上个例子打印出来的平均值要好,因为运行时间较长,这样就把开始较长的时间平摊了)。如果我们关闭V. 4 2 b i s数据压缩方式,平均值为330 ms。如果我们关闭V. 4 2错误控制方式(它同时也关闭了 V. 4 2 b i s数据压缩方式),平均值为300 ms。这些调制解调器的参数对RT T的影响很大,使用错误控制和数据压缩方式似乎效果最好。