为什么ping 192.168.072(仅2个点)会返回192.168.0.58的响应?


379

我错误地错过了IP地址并输入192.168.072
令我惊讶的是,我在192.168.0.58

如果我ping 192.168.072我会收到来自的回复192.168.0.58

为什么是这样?


我在Windows域上的Windows PC上。


如果我ping 192.168.72我从收到响应192.168.0.72,那么0in 072(由于我的原始错误)似乎很重要。


这个问题是本周超级用户问题
阅读博客条目以获取更多详细信息,或者自己撰写博客



2
有趣的是,在Linux上发生了完全相同的事情:ping 192.168.072打印PING 192.168.072 (192.168.0.58) 56(84) bytes of data.[...]。
机械蜗牛

9
更随机的是,您有一台机器192.168.0.58可以得到响应。那有几率呢?
詹姆斯·默兹

3
@KronoS如果您在学校或公司网络中,实际上并不是那么奇怪。一些DHCP服务器将按递增顺序提供地址,并且大多数将被使用。
Taum 2012年

5
192.168.0.58对我来说超时了。.是否所有ping请求都以某种方式将服务器关闭了?
iamserious

Answers:


570

每个人都使它与RFC,IP类等过分复杂。只需运行一些测试以查看ping命令如何解析用户的IP输入(去除了多余的糠壳):

> ping 1
Pinging 0.0.0.1 with 32 bytes of data:

> ping 1.2
Pinging 1.0.0.2 with 32 bytes of data:

> ping 1.2.3
Pinging 1.2.0.3 with 32 bytes of data:

> ping 1.2.3.4
Pinging 1.2.3.4 with 32 bytes of data:

> ping 1.2.3.4.5
Ping request could not find host 1.2.3.4.5. Please check the name and try again.

> ping 255
Pinging 0.0.0.255 with 32 bytes of data:

> ping 256
Pinging 0.0.1.0 with 32 bytes of data:

如您所见,该ping命令(在Windows中)允许您使用不同的IP地址格式。可以将IPv4地址分解为四个部分(“点分四进制”):,A.B.C.Dping命令允许您省略一些内容,并填写以下默认值0

1 part  (ping A)       : 0.0.0.A
2 parts (ping A.B)     : A.0.0.B
3 parts (ping A.B.C)   : A.B.0.C
4 parts (ping A.B.C.D) : A.B.C.D

如果仅提供一个零件,则它小于255(一个八位位组的最大值),则将其视为上述八位位组,但如果大于255,则将其转换并翻转到下一个字段(即mod 256)。

在某些情况下,例如提供四个以上的部分似乎行不通(例如,ping google.com的IP不适用于0.74.125.226.474.125.226.4.0)。

您也可以使用点分四进制和平面形式的十六进制表示法,但是必须通过0x在每个八位位组前加前缀来格式化它。


因此,有很多方法可以表示(IPv4)IP地址。您可以使用平面或点分四进制(或点分三重,点分双精度,甚至点分单)格式,对于每种格式,您都可以使用(甚至混合和匹配)十进制,八进制和十六进制。例如,您可以google.com通过以下方式ping通:

  • google.com  (域名)
  • 74.125.226.4  (点分十进制)
  • 1249763844  (十进制小数)
  • 0112.0175.0342.0004  (点分八进制)
  • 011237361004  (八进制单位)
  • 0x4A.0x7D.0xE2.0x04  (十六进制)
  • 0x4A7DE204  (十六进制)
  • 74.0175.0xe2.4  (ಠ_ಠ)

(感谢没有添加二进制表示法!)


应用范围

就您而言,ping 192.168.072使用上表(A.B.0.C)中的第三种格式,因此您实际上是ping 192.168.0.072。此外,由于最后一部分的前导零,它被视为八进制,十进制为58。

谜团已揭开。


注意,尽管Windows ping命令允许输入使用多种格式,并以可见的方式解释非标准格式,但这并不一定意味着您可以在任何地方使用这种格式。某些程序可能会强迫您提供点分四进制的所有四个部分,而其他程序则可能不允许混合和匹配十进制和八进制,依此类推。

同样,IPv6地址进一步使解析逻辑和输入格式的可接受性复杂化。


附录

syss指出,如果您在其中一个数字中使用了无效字符(例如,使用十六进制模式的an 8或,9当使用八进制,a g等)时,那么ping足够聪明,可以识别出该字符并将其解释为字符串(-al? -ic?)URL而不是数字IP地址。

(作为一个患有许多动脉瘤和心脏病发作的人,他们试图编写所谓的“简单”代码来适应数据值排列的指数爆炸式增长,我很欣赏,它似乎可以正确地处理所有输入变化;在这种情况下,的情况下,至少3 1 +3 2 +3 3 +3 4 = 120个变化。)

因此,尽管指定010.020.030.040将按8.16.24.32预期方式进行ping操作,但将传递010.020.030.080pingURL的方式将其视为URL而不是IP地址,就像foo.bar.baz.com可能(但遗憾的是不存在)那样。换句话说,它会尝试ping该子域010的子域020的域030在顶级域名080。但是,由于080不是有效的TLD(如.com.net和其伙伴),因此连接会在第一步失败。

090.010.010.010如果无效字符位于不同的八位字节中,也会发生相同的情况。同样,0xf.0xf.0xf.0xfping 15.15.15.15,但0xh1.0x1.0xg0.0f失败。

哦,好吧,我想这就是您不会流利使用多个数字基础所得到的。

仅确保始终使用4点分四进制(“ 40q”?“ quaaddy-quad”?“ cutie-q”?)地址可能更容易,更安全。

因此,继续学习一些数字基础。您将可以在聚会上炫耀自己,成为聚会的生活,正如他们所说,人们有10种类型:懂二进制的人和不懂二进制的人。

我们什至不用考虑 IPv6地址。我认为它们是111枚海豹之一!


39
过于复杂?实验可能非常有用,并且在这种情况下产生了很好的答案。但是如果没有理论,文档或标准,您可能会错过一个关键因素,却一无所知。或者,您可能正在确定一个特定版本的工作方式,并且在那里大约90%的实现都出错了。或者,您可以提出解释实验结果的规则,但比预期的规则复杂。在这种情况下,我认为文档的规则(for inet_aton())在一个方面更简单-没有“低于/超过255”的条件。
LarsH 2012年

71
你看!计算机科学的“科学”部分应运而生!(假设,实验,验证)
Izkata 2012年

13
@LarsH,这就是我的观点,该ping命令(至少在Windows上是)类似于Microsoft的许多程序(尤其是臭名昭著的IE)。它试图太宽容,拿走你扔给它的任何东西,并试图解释它。是的,有一个关于IP地址格式的官方文档,但这不是关于ISO和RFC的问题,它是实用的,我做了一些事情,这是一个很奇怪的问题,可以不借助(公认的冗长,干燥,无聊)来回答。技术规范)—尽管OP希望阅读它们也可以链接到它们。
Synetech

6
0前缀的八进制解析应完全放弃,除了chmod。而已。这是八进制的唯一例外。期。
詹姆斯·邓恩

6
对于将RGB HEX转换为DEC很有用。哈哈〜C:\>ping 0xffffcc Pinging 0.255.255.204 with 32 bytes of data:
威尔逊

147

有两个原因:

首先,前缀“ 0”表示八进制数。由于oct(072)= dec(58),因此192.168.072 = 192.168.58。

其次,倒数第二个0可以作为简写从IP地址中删除。127.0.1被解释为127.0.0.1,在您的情况下192.168.58被解释为192.168.0.58。


7
它不会将零分组。实际上,它将每个点视为与下一个字节边界相对应的分隔符。因此,IP地址2130706433和127.0.0.1是相同的地址。
Serge

2
更精确的是,在IP地址的情况下是四点符号
Guillaume86

4
著名的前导零再次击中!
卢克M

2
现在,这才是真正的答案!
l --''''''------------''''''''''''2012年

2
这个答案是不正确的,具有误导性。在1.0.2.3(1.2.3)中添加0会得到一个不同的IP地址(1.2.0.3)。
sch 2012年

101

除了@ neu242关于八进制表示法的要点,以及观察到IP地址可以缩短之外,另一个关键部分是知道如何解释缩短的IP地址。

可能会天真地猜测,如果缺少四个数字,则解析器会将零填充字节添加到字节序列的末尾(或开头)。但这与OP报告的行为不符:192.168.072被解析为192.168。0 .58,而不是192.168.58。00 .192.168.58。

显然,Windows和Linux ping(您尝试过的版本以及我尝试过的版本)使用了与inet_aton()等效的功能来解析IP地址参数。inet_aton()手册页显示

The address supplied in cp can have one of the following forms:

 a.b.c.d   Each of the four numeric parts specifies a byte of the address; the
           bytes are assigned in left-to-right order to produce the binary
           address.

 a.b.c     Parts a and b specify the first two bytes of the binary address.
           Part c is interpreted as a 16-bit value that defines the rightmost
           two bytes of the binary address.  This notation is suitable for
           specifying (outmoded) Class B network addresses.

 a.b       Part a specifies the first byte of the binary address.  Part b is
           interpreted as a 24-bit value that defines the rightmost three bytes
           of the binary address.  This notation is suitable for specifying
           (outmoded) Class C network addresses.

 a         The value a is interpreted as a 32-bit value that is stored directly
            into the binary address without any byte rearrangement.

因此,您拥有了它... 192.168.072适合abc模式,因此072(解析为八进制数之后)被解释为16位值,该值定义了二进制地址的最右边2个字节,等效于0.58

上面的规则等同于说,如果缺少四个数字,则在给定的最后一个数字之前立即添加所需的零填充字节,而不是在字节串的末尾或开头。(如果给定的最后一个数字小于256,则可以用这种方式表示。)

请注意,较新版本的ping可能不允许这种简写形式,也不允许八进制解释。我发现的iputils(包括ping)的2010年源代码使用inet_pton()而不是inet_aton()来解析IP地址参数。inet_pton()手册页显示

与inet_aton(3)和inet_addr(3)不同,inet_pton()支持IPv6地址。另一方面,inet_pton()仅接受点分十进制表示法的IPv4地址,而inet_aton(3)和inet_addr(3)允许使用更通用的数字和点表示法(十六进制和八进制数字格式,以及不支持t要求将所有四个字节显式写入)。


12
到目前为止,这是恕我直言的最佳答案。
2012年

在Windows上,您正在inet_addrWinsock中
user7116 2013年

24

您还必须考虑到ip可以由整数加起来来表示,这些整数在其位置上有意义。

192.168.0.58 is :
  192 * 256^3
+ 168 * 256^2
+   0 * 256^1
+  58 * 256^0

这是很酷的事情:

192.168.58将为192.168.0.58,因为

    0 * 256^1 
+  58 * 256^0 
=  58

192.11010106也将是192.168.0.58,因为

  168 * 256^2 
+   0 * 256^1 
+  58 * 256^0 
= 11010106

3232235578也将是192.168.0.58,因为

  192 * 256^3 
+ 168 * 256^2 
+   0 * 256^1 
+  58 * 256^0 
= 3232235578

1
“ 192.168.56将是192.168.0.56,因为0 * 256 ^ 1 + 58 * 256 ^ 0 = 58”您确定吗?您希望在第一种情况下168乘以256 ^ 1,在第二种情况下乘以256 ^ 2。类似地,将192乘以256 ^ 2与256 ^ 3。因此,如果还有其他规则(例如,丢弃零),则192.168.56只能= 192.168.0.56。
LarsH 2012年

@LarsH,我认为这里要说的是它是从左到右的,这与“正常”计数是指从1算起的所有基数不同。因此,第一个点导致其左侧的任何内容乘以256 ^ 3,第二个点与256 ^ 2相乘,第三个点与256相乘。如果在其左侧没有点,则将其乘以256 ^ n。所以1.2.3。如果我理解正确,则(1.2.3.0)与1.2.3(1.2.0.3)会有所不同。
iX3 2012年

@ iX3:如果是这种情况,则“ 192.168.56将为192.168.0.56”将是错误的,因为在第一种情况下,56将乘以256 ^ 1,而在第二种情况下,仅将56乘以y 256 ^ 0。并且OP的192.168.072将解释为192.168.58.0而不是192.168.0.58。
LarsH 2012年

有点误导的是,地址为0的事实是第三个数字。考虑该地址192.168.1.56,三位数字格式为192.168.312,因为1 * 256 ^ 1 + 56 * 256 ^ 0为312
vesquam 2012年

1
点仅用于描述应乘以256的幂的数字。解析器将查找第一个点,并将其前的数字乘以256 ^ 3。重复第2点和第3点,但分别重复256 ^ 2和256 ^ 1。然后,它将所有结果加在一起(尽管结果相同,但有些隐含内容可能会保持运行总计)。如果这些点中的任何一个丢失,它只是不进行乘法运算,而只是将最终数字加到运行的总数中。这也是1.2.3.导致错误的原因,因为解析器找不到要添加到总数中的最后一个数字。
贾斯汀(Justin)2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.