題 為什麼ping 192.168.072(只有2個點)從192.168.0.58返迴響應?


我錯誤地錯過了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,所以看來 0 在 072 (在我原來的錯誤中)很重要。


這個問題是一個 本週超級用戶問題
閱讀 博客文章 了解更多詳情或 為博客做貢獻 你自己


373
2017-10-12 10:26


起源


相關:  blog.superuser.com/2012/02/10/wtfriday-http2915189091 - Tom Wijsman
有趣的是,在Linux上發生了同樣的事情: ping 192.168.072 版畫 PING 192.168.072 (192.168.0.58) 56(84) bytes of data.[...]。 - Mechanical snail
更隨機的是你有一台機器 192.168.0.58 得到回應。有什麼可能性? - KronoS
@KronoS如果你在學校或公司網絡上,它實際上並不那麼奇怪。一些DHCP服務器將按遞增順序提供地址,並且將使用大多數地址。 - Taum
192.168.0.58 正在為我超時..所有ping請求都能以某種方式淘汰服務器?! - iamserious


答案:


每個人都使用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.D,和 ping 命令允許你留出一些,填寫默認值 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.4 要么 74.125.226.4.0)。

您也可以使用虛線四邊形和平面形式的十六進製表示法,但必須通過預先掛起來格式化 0x 到每個八位字節。


因此,有很多方法可以表示(IPv4)IP地址。您可以使用平面或點四邊形(或點三面,點雙面,甚至點單面)格式,對於每種格式,您可以使用(甚至混合和匹配)十進制,八進制和十六進制。例如,你可以ping google.com 通過以下方式:

  • 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指出 如果您在其中一個數字中使用無效字符(例如, 8 要么 9 當使用八進制時,a g 在十六進制模式等)然後 ping 是否足夠智能識別並將其解釋為字符串(-al?-ic?)URL而不是數字IP地址。

(作為一個有很多動脈瘤和心髒病發作的人試圖編寫所謂的“簡單”代碼以適應數據值的指數級數量排列,我欣賞它 - 似乎 - 正確處理所有輸入變化;在此案例,至少31+32+33+34=120 變化。)

所以,在指定時 010.020.030.040 會ping 8.16.24.32 正如所料,過世 010.020.030.080 至 ping 將被視為URL而不是IP地址 foo.bar.baz.com 這可能(但遺憾的是)不存在。換句話說,它嘗試ping子域 010 在子域名上 020 在域上 030 在頂級域名 080。但是,自從 080 不是有效的頂級域名(如 .com.net和他們的伙伴們一樣,連接在第一步就失敗了。

同樣的事情發生在 090.010.010.010 無效字符在不同的八位字節中。同樣, 0xf.0xf.0xf.0xf 坪 15.15.15.15但是 0xh1.0x1.0xg0.0f 失敗。

哦,我想這就是你不能流利地使用多個數字庫。

確保始終使用4點四方(“40q”?“quaddy-quad”?“cutie-q”?)地址可能更容易,更安全。

所以出去吧 學習一些數字基礎。你將能夠炫耀並成為派對的生命,正如他們所說,有10種類型的人:知道二元的人和不知道的人。

我們不是 認為 關於IPv6地址;我認為他們是111封印章之一!


568
2017-10-12 17:06



過於複雜?實驗可能非常有用,在這種情況下產生了很好的答案;但如果沒有理論,文獻或標準,你可能會錯過一個關鍵因素而不知道它。或者你可以確定一個特定版本的工作方式,並且90%的實現都是錯誤的。或者你可以提出解釋你的實驗結果的規則,但比預期的規則更複雜。在這種情況下,我認為文件的規則(為 inet_aton())在一方面更簡單 - 沒有“低於/高於255”的條件。 - LarsH
你看!計算機科學的“科學”部分出現了! (假設,實驗,驗證) - Izkata
@LarsH,這是我的觀點,但是 ping 命令(至少在Windows上)就像許多微軟的程序(尤其是臭名昭著的)IE。它試圖過於寬容,拿走任何東西,然後試圖解釋它。是的,有關於IP地址格式的官方文檔,但這不是關於ISO和RFC的問題,它是實用的, 我做了一件事,這很奇怪 這個問題可以在不訴諸的情況下得到解答(誠然是漫長,乾燥,無聊的技術規範) - 雖然如果OP想要閱讀它們,那麼鏈接它們也很好。 - Synetech
應該完全放棄0前綴的八進制解析,除了 chmod。而已。這是八角形允許的唯一例外。期。 - James Dunne
它對RGB HEX到DEC轉換很有用。哈哈〜 C:\>ping 0xffffcc  Pinging 0.255.255.204 with 32 bytes of data: - wilson


有兩個原因:

首先,'0'前綴表示 八進制 數。由於oct(072)= dec(58),192.168.072 = 192.168.58。

其次,倒數第二個0可以從IP地址中刪除為a 速記。 127.0.1被解釋為127.0.0.1,在您的情況下,192.168.58被解釋為192.168.0.58。


147
2017-10-12 10:39



它不會將零分組。它實際上將每個點視為對應於下一個字節邊界的分隔符。因此,IP地址2130706433和127.0.0.1是相同的地址。 - Serge
32位數字的x.x.x.x表示法是否有名稱?它可能在其他域中使用/有用,但我不能谷歌它:)編輯:nevermind,它是點十進製表示法 - Guillaume86
更準確地說,它是IP地址情況下的四點劃線表示法 - Guillaume86
著名的領先零度再次擊中! - Luc M
現在這是真正的答案! - l--''''''---------''''''''''''


除了@ neu242關於八進製表示法的重要觀點,以及可以縮短IP地址的觀察之外,另一個關鍵部分是了解如何解釋縮短的IP地址。

人們可能會天真地猜測,如果缺少四個數字中的一些,解析器會將零填充字節添加到字節序列的末尾(或開頭)。但這與OP報告的行為不匹配:192.168.072被解析為192.168。0.58,而不是192.168.58。0,也不是 0.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 適合a.b.c模式,所以 072 (在解析為八進制數後)被解釋為一個16位值,它定義了二進制地址最右邊的2個字節,相當於 0.58

上述規則等同於說如果缺少四個數字中的任何一個,則添加所需的零填充字節 在最後一個號碼之前...不在字符串的最後或開頭。 (如果給出的最後一個數字小於256,則以這種方式表示。)

請注意,較新版本的ping可能不允許這種速記,也不允許八進制解釋。該 2010年iputils的源代碼 我找到的(包括ping)使用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)允許更通用   數字和點符號(十六進制和八進制數字格式,和   不需要顯式寫入所有四個字節的格式。


98
2017-10-12 15:33



這是迄今為止最好的答案恕我直言。 - Josh
在Windows上,你正在尋找 inet_addr 在溫索克。 - user7116


你還必須考慮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

25
2017-10-12 13:57



“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
@LarsH,我認為這裡所說的是它是從左到右的基礎,不像“正常”計數,我們從1的位置開始。所以第一個點導致它左邊的任何東西乘以256 ^ 3,第二個點乘以256 ^ 2,第三個點乘以256.如果它左邊沒有點,那麼它將被添加w / o乘以256 ^ N。所以1.2.3。如果我理解正確,(1.2.3.0)將與1.2.3(1.2.0.3)不同。 - iX3
@ iX3:如果是這種情況,那麼“192.168.56將是192.168.0.56”將是不正確的,因為在第一種情況下,56將乘以256 ^ 1,而在第二種情況下,56只會成倍增加是256 ^ 0。 OP的192.168.072將被解釋為192.168.58.0而不是192.168.0.58。 - LarsH
有點誤導的是地址為0的事實有第3位數。考慮此地址192.168.1.56 3位數形式為192.168.312因為1 * 256 ^ 1 + 56 * 256 ^ 0是312 - vesquam
這些點僅​​用於描述哪些數字應乘以256的冪。解析器查找第一個點,並將其前面的數字乘以256 ^ 3。重複第2和第3個點,但分別按256 ^ 2和256 ^ 1。然後它將所有結果加在一起(一些impl。可能會保持運行總計,但結果是相同的)。如果缺少任何這些點,它就不會進行乘法,只是將最終數字加到運行總計中。這也是原因 1.2.3. 導致錯誤,因為解析器無法找到要添加到總數的最後一個數字。 - Justin ᚅᚔᚈᚄᚒᚔ