Это довольно сложная проблема, с которой, к моему удивлению, сегодня у меня была проблема.
Мне кажется, что inet_pton и inet_ntoa изменяют байты IP-адреса, который они задают:
DWORD IP; inet_pton(AF_INET, "192.168.0.1", &IP); printf("%08X\n", IP);
Это напечатает 0100A8C0
. И хорошо, если мы 01.00.A8.C0 = 1.0.168.192
байты, это 01.00.A8.C0 = 1.0.168.192
.
Так же:
IP = 0x7F000001; struct in_addr ia; ia.S_un.S_addr = IP; printf("%s\n", inet_ntoa(ia));
дает мне 1.0.0.127
.
Первое, что приходит на ум, – это утверждение, но я прочитал документацию MSDN ( 1 и 2 ), и порядок байтов не упоминается; мне кажется странным, что эти функции произвольно решат использовать одно из обозначений без спецификации, явно заявляя об этом.
Что здесь происходит?
Эндианность – причина.
Вся суть этих функций заключается не в создании «читаемого» целого числа, а в установке 32-битного количества, которое готово к отправке на провод. IPv4 требует упорядочивания по большому счету, поэтому я бы сделал ставку, если вы сделали printf("%02X\n", ((char *)&IP)[0]));
, вы получите C0
.
Количества, превышающие размер байта (шорты, целые числа и т. Д.), Должны оставить провод в сетевом порядке в соответствии с требованиями интернет-стандарта, который по умолчанию имеет значение Big-endian.
Таким образом, эти функции, такие как inet_pton
, inet_ntoa
, htons
, htonl
и другие подобные, отвечают за замену байтов в этих количествах в зависимости от конечности хоста. С другой стороны, приемник должен использовать соответствующие функции для преобразования сетевого байта в соответствующий порядок байтов.