Почему пинг 192.168.072 (только 2 точки) возвращает ответ от 192.168.0.58?

378

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

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

Почему это?


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


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


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

Джордж Дакетт
источник
9
Соответствует: blog.superuser.com/2012/02/10/wtfriday-http2915189091
Тамара Вийсман,
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-серверы будут давать адреса в порядке возрастания, и большинство из них будут использоваться.
Таум
5
192.168.0.58тайм-аут для меня .. может все запросы ping каким-то образом выбили сервер ?!
яростный

Ответы:

569

Все слишком усложняют это с 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).

Есть несколько случаев краев , как обеспечение более четырех частей , кажется, не работают (например, пинг google.comIP «s не будет работать либо 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), так что вы на самом деле ping 192.168.0.072. Кроме того, поскольку у вас есть ведущий ноль в последней части, он обрабатывается как восьмеричное число, которое в десятичной дроби равно 58.

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


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

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


Приложение :

syss отметил, что если вы используете недопустимый символ в одном из чисел (например, 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как и ожидалось, проходя 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не получается.

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

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

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

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

Synetech
источник
39
Усложнять? Экспериментирование может быть очень полезным, и в этом случае дает хороший ответ; но без теории, документации или стандартов вы можете упустить критический фактор и не знать его. Или вы можете определить, как работает одна конкретная версия, и ошибаться в 90% реализаций. Или вы могли бы придумать правила, которые объясняют результаты ваших экспериментов, но являются более сложными, чем предполагаемые правила. В этом случае я думаю, что правила документирования (для inet_aton()) проще в одном отношении - никаких условий для «меньше / больше 255».
LarsH
71
Эй смотри! «Наука» часть компьютерных наук появляется! (предположить, поэкспериментировать, проверить)
Изката
13
@LarsH, но я хочу сказать, что pingкоманда (по крайней мере, для Windows) подобна многим программам Microsoft (особенно пресловутым) IE. Он пытается быть слишком прощающим и брать все, что вы в него бросаете, и пытается его интерпретировать. Да, есть официальный документ о форматах IP-адресов, но это не вопрос ISO и RFC, это практично, я что-то сделал, и это странный вопрос, на который можно ответить, не прибегая к (по общему признанию, длинному, сухому, скучному технические спецификации) - хотя ссылки на них на случай, если ФП захочет их прочитать, тоже хороши.
Synetech
6
0-префиксный восьмеричный синтаксический анализ должен быть полностью оставлен, за исключением chmod. Вот и все. Это единственное исключение для восьмеричного кода. Период.
Джеймс Данн
6
это полезно для преобразования RGB HEX в DEC. LOL ~C:\>ping 0xffffcc Pinging 0.255.255.204 with 32 bytes of data:
Уилсон
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.

neu242
источник
7
Он не группирует нули. Фактически каждая точка рассматривается как разделитель, соответствующий границе следующего байта. Таким образом, IP-адреса 2130706433 и 127.0.0.1 являются одинаковыми адресами.
Серж
2
точнее, это запись с четырьмя точками в случае IP-адреса
Guillaume86
4
Знаменитый ведущий ноль ударил еще раз!
Люк М
2
теперь это реальный ответ!
l --''''''--------- '' '' '' '' '' ''
2
Этот ответ неверен и вводит в заблуждение. Удаление 0 в 1.0.2.3 (1.2.3) дает другой IP-адрес (1.2.0.3).
щ
101

В дополнение к важному замечанию @ 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 (включая пинг) , которые я нашел использует 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) допускают более общие обозначения чисел и точек (шестнадцатеричные и восьмеричные числовые форматы, а также форматы, которые не не требуется, чтобы все четыре байта были записаны явно).

LarsH
источник
12
Это, безусловно, лучший ответ ИМХО.
Джош
На Windows вы ищете inet_addrв Winsock.
user7116
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
vesquam
источник
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
@LarsH, я думаю, что здесь говорится о том, что он основан слева направо, в отличие от «нормального» подсчета, когда мы основываем все с 1-го места. Таким образом, первая точка приводит к умножению всего, что слева от нее, на 256 ^ 3, второй на 256 ^ 2, третьей на 256. Если слева от нее нет точки, то она добавляется без умножения на 256 ^ п. Итак 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. И ОП 192.168.072 будет интерпретироваться как 192.168.58.0 вместо 192.168.0.58.
LarsH
Что немного вводит в заблуждение, так это тот факт, что адрес имеет 0 и имеет 3-ю цифру. Рассмотрим этот адрес 192.168.1.56. Трехзначная форма будет 192.168.312, поскольку 1 * 256 ^ 1 + 56 * 256 ^ 0 равно 312
vesquam
1
Точки служат только для того, чтобы определить, какие числа должны быть умножены на степень 256. Парсер ищет первую точку и умножает число перед ней на 256 ^ 3. Повторите для 2-й и 3-й точки, но с 256 ^ 2 и 256 ^ 1 соответственно. Затем он складывает все результаты вместе (некоторые из них могут содержать промежуточные итоги, хотя результат остается тем же). Если какая-либо из этих точек отсутствует, она просто не выполняет умножение, а просто добавляет окончательное число к итоговой сумме. По этой же причине 1.2.3.возникает ошибка, потому что парсер не может найти последнее число для добавления к общему количеству.
Джастин,