374

Я по ошибке пропустил точку IP-адреса и набрал 192.168.072 .
К моему удивлению я подключился к машине в 192.168.0.58

Если я пинг 192.168.072 я получаю ответы от 192.168.0.58 .

Почему это?


Я на ПК с Windows в домене Windows.


Если я пингую 192.168.72 я получаю ответ от 192.168.0.72 , поэтому кажется, что 0 в 072 (в моей первоначальной ошибке) является значительным.


Этот вопрос был Супер Вопросом Пользователя Недели.
Прочитайте запись в блоге для более подробной информации или внесите свой вклад в блог самостоятельно

4 ответа4

567

Все чрезмерно усложняют это с 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).

Есть несколько крайних случаев, когда кажется, что предоставление более четырех частей не работает (например, пинг IP-адреса google.com не будет работать ни для 0.74.125.226.4 ни для 74.125.226.4.0).

Вы также можете использовать шестнадцатеричную нотацию как в точечно-четырехугольной, так и в плоской форме, но необходимо отформатировать ее, предварительно ожидая 0x для каждого октета.


Таким образом, существует множество способов представления IP-адреса (IPv4). Вы можете использовать плоский или точечно-четырехугольный (или точечно-тройной, точечно-двойной или даже точечно-одиночный) формат, и для каждого вы можете использовать (или даже смешивать и сочетать) десятичные, восьмеричные и шестнадцатеричные. Например, вы можете пропинговать google.com следующими способами:

  • google.com (доменное имя)
  • 74.125.226.4 (десятичный пунктир)
  • 1249763844 (десятичная дробь)
  • 0112.0175.0342.0004 (восьмеричный пунктир)
  • 011237361004 (плоский восьмеричный)
  • 0x4A.0x7D.0xE2.0x04 (пунктирный гекс)
  • 0x4A7DE204 (плоский гекс)
  • 74.0175.0xe2.4 (ಠ_ಠ)

(Слава Богу, что поддержка двоичной нотации не была добавлена!)


Применение:

В вашем случае pinging 192.168.072 использует третий формат в приведенной выше таблице (A.B.0.C), так что вы на самом деле пингуете 192.168.0.072 . Кроме того, поскольку у вас есть ведущий ноль в последней части, он обрабатывается как восьмеричное число, которое в десятичной дроби равно 58.

Тайна разгадана.


Обратите внимание, что хотя команда ping в Windows допускает столь широкое разнообразие форматов ввода и интерпретирует нестандартные форматы видимыми способами, это не обязательно означает, что вы можете использовать такие форматы везде. Некоторые программы могут вынудить вас предоставить все четыре части точечного квадрата, другие могут не допустить смешивания и сопоставления десятичных и восьмеричных чисел и т.д.

Кроме того, адреса IPv6 еще больше усложняют логику синтаксического анализа и приемлемость формата ввода.


Приложение:

syss указал, что если вы используете недопустимый символ в одном из чисел (например, 8 или 9 при использовании восьмеричного, g в шестнадцатеричном режиме и т. д.), тогда ping достаточно умен, чтобы распознать его и интерпретировать как строку (-al? -ic?) URL вместо цифрового IP-адреса.

(Как человек, который имел многочисленные аневризмы и сердечные приступы, пытался написать предположительно «простой» код, чтобы приспособиться к экспоненциально растущему числу перестановок значений данных, я ценю, что он - кажется, - правильно обрабатывает все входные варианты; в этом случай, как минимум 3 1+3 2+3 3+3 4 = 120 вариаций.)

Таким образом, при указании 010.020.030.040 ping 8.16.24.32 как и ожидалось, передача 010.020.030.080 в ping будет обрабатываться как URL, а не как IP-адрес - как foo.bar.baz.com который может (но, к сожалению, не существует) существовать , Другими словами, он пытается пропинговать субдомен 010 на субдомене 020 в домене 030 в домене верхнего уровня 080 . Однако, так как 080 не является допустимым TLD (например, .com , .net и их друзьями), соединение завершается неудачно прямо на первом этапе.

То же самое происходит с 090.010.010.010 где недопустимый символ находится в другом октете. Аналогично, 0xf.0xf.0xf.0xf пингует 15.15.15.15 , но 0xh1.0x1.0xg0.0f завершается ошибкой.

О, хорошо, я полагаю, это то, что вы получаете за то, что не владеете несколькими базами чисел.

Вероятно, проще и безопаснее просто убедиться, что всегда используется 4-точечный квадрат («40q»? «Quaddy-квад»? «Милашка-д»?) адреса.

Так что иди и выучить некоторые числовые основы. Вы сможете похвастаться жизнью вечеринок, и, как говорится, существует 10 типов людей: тех, кто знает двоичный код, и тех, кто этого не знает.

Давайте даже не будем думать об IPv6-адресах; Я думаю, что они одна из 111 печатей !!!

147

Для этого есть две причины:

Во-первых, префикс «0» обозначает восьмеричное число. Поскольку окт (072) = декабрь (58), 192.168.072 = 192.168.58.

Во-вторых, второй-последний 0 может быть сброшен с IP-адресов как сокращение. 127.0.1 интерпретируется как 127.0.0.1, а в вашем случае 192.168.58 интерпретируется как 192.168.0.58.

100

В дополнение к важному замечанию @ neu242 о восьмеричной нотации и наблюдению о том, что IP-адреса могут быть сокращены, другой важной частью является знание того, как интерпретируются сокращенные IP-адреса.

Можно наивно предположить, что, если некоторые из четырех чисел отсутствуют, парсер добавил бы заполненные нулями байты в конец (или начало) последовательности байтов. Но это не соответствует поведению, о котором сообщил OP: 192.168.072 был проанализирован как 192.168. 0.58, а не 192.168.58. 0 или 0.192.168.58.

Очевидно, что ping для Windows и Linux (версия, которую вы пробовали, и версия, которую я пробовал) использует что-то эквивалентное inet_aton () для анализа аргумента IP-адреса. Страница man для 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 могут не разрешать такого рода сокращения или восьмеричное толкование. Исходный код 2010 для iputils (включая ping), который я обнаружил, использует inet_pton (), а не inet_aton () для анализа аргумента IP-адреса. Страница man для inet_pton () говорит:

В отличие от inet_aton(3) и inet_addr(3), inet_pton() поддерживает адреса IPv6. С другой стороны, inet_pton() принимает адреса IPv4 только в точечно-десятичном формате, тогда как inet_aton(3) и inet_addr(3) допускают более общие обозначения чисел и точек (шестнадцатеричные и восьмеричные числовые форматы и форматы, которые не не требуется, чтобы все четыре байта были записаны явно).

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .