如果我们使用ICMP的ping,我们知道TTL和round-trip time存储在IP标头中。在下面的IP标头图中,我们知道TTL的位置,但是往返时间在哪里?



是否存储在Options中?

#1 楼

往返时间实际上并未存储在任何地方。发送主机使用ICMP的16位标识符和序列字段来记住发送每个ICMP Echo Request消息的时间。当它收到ICMP Echo Reply时,它会记下当前时间,找到发送该答复所标识的匹配Request数据包的时间,计算差异并报告。

通常ping使用ICMP的标识字段区分多个同时执行的ping操作,并区分序列字段以区分各个数据包。

决定将给定数据包的传出时间存储在哪里:而不是将其存储在主机中一个表,通常在外发请求中将其发送,并在回复中使用副本来计算时间。 (感谢评论者指出这一点。)它以便于实现的任何方式发送,并且当然必须信任远端以及任何介入的设备才能正确复制数据。已知某些系统以微秒的分辨率以16字节表示时间,有些以毫秒的分辨率以8字节表示时间。

IP数据包data部分内部的格式为ICMP回显请求/应答消息,从RFC 792“ Internet控制消息格式”(p14)复制到此处。

Type对于“请求”为8,对于“答复”为0; Code为0。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Identifier          |        Sequence Number        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Data ...
   +-+-+-+-+-


PS。请注意,IP标头的标识字段通常设置为任意值,每个传出数据包都不同,用于重组任何碎片,并且与ICMP主体中的值不相同。

此外,尽管定义了一种机制来将时间戳记作为选项添加到IP报头中,但这不是正常的ping机制,因为很多路由器都配置为不传递某些IP选项。请参阅Internet协议时间戳选项的RFC 781规范。

最后,尽管这里的所有内容都是从IPv4角度编写的,但仍是最初的问题。但是IPv6中的ping非常相似,请参阅ICMPv6 RFC4443。

评论


AIUI的“标识”字段用于标识用于片段重组的数据包。回声请求通过ICMP头中的id和seq字段与回声答复进行匹配。

– Peter Green
18/09/14在15:14

感谢您指出:我澄清说,这是ICMP而不是IP ID(和您所说的seq)。

– jonathanjo
18/09/14在18:33



我很确定在Linux上至少有一种ping实现,它将时间戳存储在ICMP有效负载的Data部分中。当回声答复遍历一个互联网交换时,这会导致一些非常有趣的错误消息,该互联网交换破坏了每个数据包中该位置的某个位。

–卡巴斯德
18-09-14在20:13

您当然是对的,我更新了答案,这样说;尽管自然地,存储的是根据发送方时钟发送的绝对时间,而不是RTT本身。

– jonathanjo
18/09/15在13:02

#2 楼

至少使用Linux上常见的ping实用程序,发送数据包的时间存储在回显请求数据包的数据部分中,即IP和ICMP标头之后。当接收方以回声答复进行答复时,数据部分保持不变,因此发送方可以计算往返时间。 DETAILS“):


如果数据空间至少为q4312079的大小,则ping使用此空间的
起始字节包括它在
往返时间的计算。如果数据空间较短,则没有给出往返时间。


在我的计算机上,ping为16,因此将数据包数据大小设置为15会阻止struct timeval显示往返时间:

$ ping -s 15 8.8.8.8 
PING 8.8.8.8 (8.8.8.8) 15(43) bytes of data.
23 bytes from 8.8.8.8: icmp_seq=1 ttl=121


当然,如@jonathanjo的回答所描述的那样,将发送时间戳存储在实用程序中也是可行的。甚至Linux实用程序也需要一些内部记账,因为它可以检测到重复的数据包。

评论


当您将数据大小设置为小于16时,它们无法显示RTT感觉就像是一个程序错误。

–canadadry
18-09-14在20:32

@canadadry,好吧,将时间戳记放入数据包本身是显而易见的:唯一需要的情况是答复数据包到来时,因此在本地存储它毫无用处。当然,该程序似乎源于80年代BSD的原始版本,因此它也可能与时代有关。无论如何,我不确定为什么有人会使用这种超小的数据包。请注意,即使最小的以太网帧大小也足以容纳以太网,IP和ICMP标头以及16字节的时间戳。 (尽管还有2个字节,所以没有足够的空间进行进一步扩展。)

–ilkkachu
18/09/15在2:15

@ilkkachu感谢您提醒我时间通常存放在哪里;我更新了答案。关于微小的数据包:许多网络问题在数据包大小上有所不同。

– jonathanjo
18-09-15在13:04

@ikkachu我看了一下Cisco的ping数据包:它们也有时间,以毫秒为单位的64位计数。

– jonathanjo
18/09/15在15:28