🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
我们可以写一个简单程序(取名为icmptime),给某个主机发送ICMP时间戳请求,并打印出返回的应答。它在我们的小互联网上运行结果如下: ![](https://box.kancloud.cn/2016-04-13_570de1e9544b7.png) 程序打印出ICMP报文中的三个时间戳:发起时间戳(orig)、接收时间戳(recv)以及发送时间戳(xmit)。正如我们在这个例子以及下面的例子中所看到的那样,所有的主机把接收时间戳和发送时间戳都设成相同的值。 我们还能计算出往返时间(rtt),它的值是收到应答时的时间值减去发送请求时的时间值。difference的值是接收时间戳值减去发起时间戳值。这些值之间的关系如图6-7所示。 ![](https://box.kancloud.cn/2016-04-13_570de1e964db9.png) 如果我们相信RTT的值,并且相信RTT的一半用于请求报文的传输,另一半用于应答报文的传输,那么为了使本机时钟与查询主机的时钟一致,本机时钟需要进行调整,调整值是difference减去RTT的一半。在前面的例子中, bsdi的时钟比sun的时钟要慢7 ms和8 ms。 由于时间戳的值是自午夜开始计算的毫秒数,即UTC,因此它们的值始终小于86400000 (24×60×60×1000)。这些例子都是在下午4:00以前运行的,并且在一个比UTC慢7个小时的时区,因此它们的值比82800000(2300小时)要大是有道理的。 如果对主机bsdi重复运行该程序数次,我们发现接收时间戳和发送时间戳的最后一位数总是0。这是因为该版本的软件(0.9.4版)只能提供10ms的时间分辨率(说明参见附录B)。 如果对主机svr4运行该程序两次,我们发现SVR4时间戳的最后三位数始终为0: ![](https://box.kancloud.cn/2016-04-13_570de1e97badd.png) 由于某种原因, SVR4在ICMP时间戳中不提供毫秒级的分辨率。这样,对秒以下的时间差调整将不起任何作用。 如果我们对子网140.252.1上的其他主机运行该程序,结果表明其中一台主机的时钟与sun相差3.7秒,而另一个主机时钟相差近75秒: ![](https://box.kancloud.cn/2016-04-13_570de1e98db9d.png) 另一个令人感兴趣的例子是路由器gateway(一个Cisco路由器)。它表明,当系统返回一个非标准时间戳值时(不是自午夜开始计算的毫秒数, UTC),它就用32 bit时间戳中的高位来表示。我们的程序证明了一点,在尖括号中打印出了接收和发送的时间戳值(在关闭高位之后)。另外,不能计算发起时间戳和接收时间戳之间的时间差,因为它们的单位不一致。 ![](https://box.kancloud.cn/2016-04-13_570de1e99f7f0.png) 如果我们在这台主机上运行该程序数次,会发现时间戳值显然具有毫秒级的分辨率,而且是从某个起始点开始计算的毫秒数,但是起始点并不是午夜UTC(例如,可能是从路由器引导时开始计数的毫秒数)。 作为最后一个例子,我们来比较sun主机和另一个已知是准确的系统时钟—一个NT Pstratum1服务器(下面我们会更多地讨论NTP,网络时间协议)。 ![](https://box.kancloud.cn/2016-04-13_570de1e9b1abc.png) 如果我们把difference的值减去RTT的一半,结果表明sun主机上的时钟要快38.5~51.5 ms。