Тот же вывод для htonl() и ntohl() для целого числа
Я запустил следующую программу на машине little-endian [LE] [Linux, процессор Intel]. Я не могу объяснить три вывода в ниже фрагменте кода. Так как машина LE, значение a
сохраняется как 0x78563412
. При печати отображается фактическое значение. Начиная с его машины LE, я ожидаю, что ntohl()
будет no-op и отобразит 0x78563412
, что он делает. Тем не менее, я ожидаю, что 0x12345678
для второго оператора печати, содержащего htonl()
. Может кто-то, пожалуйста, помогите мне понять, почему они такие же?
int main()
{
int a = 0x12345678;
printf("Original - 0x%x\n", (a));
printf("Network - 0x%x\n", htonl(a));
printf("Host - 0x%x\n", ntohl(a));
return 0;
}
Вывод:
Original - 0x12345678
Network - 0x78563412
Host - 0x78563412
Ответы
Ответ 1
Начиная с его машины LE, я ожидаю, что ntohl()
будет no-op
Это ошибка. Сетевой порядок байтов является бай-ином, порядок байтов хоста носит малозначительный характер. Поэтому как ntohl
и htonl
возвращают байтовую версию их ввода.
Помните, что точка htonl
состоит в том, что вы можете взять целое число на хосте, а затем написать:
int i = htonl(a);
и результатом является то, что память i
, когда интерпретируется с использованием сетевого порядка следования байтов, имеет то же значение, что делает. a
Следовательно, если вы пишете представление объекта i
в сокет, а читатель с другого конца ожидает целое число из 4 байтов в сетевом байтовом порядке, он будет читать значение a
.
и дисплей 0x78563412
Это то, что вы намеревались написать? Если ntohl
был не-op (вернее, функцией идентификации), то ваша третья строка обязательно напечатала бы то же самое, что и ваша первая строка, потому что у вас было бы ntohl(a) == a
. Это то, что происходит в реализациях большого конца, где печатается ваша программа:
Original - 0x12345678
Network - 0x12345678
Host - 0x12345678
Ответ 2
htonl
и ntohl
- это точно такие же функции. Предполагается, что они удовлетворяют htonl(ntohl(x)) == x
. Они называются по-разному только для документации (вы делаете это явным, что вы конвертируете из хоста в сеть или наоборот, даже если это то же самое). Таким образом, на машине с маленькими терминами они выполняют как байтовую замену, так и на машине большого конца, они оба не работают.
Ответ 3
Потому что вы передаете по значению и, следовательно, не изменяется ни одним из этих функций. a
Вы печатаете то, что htonl()
и ntohl()
.
Изменить, чтобы добавить: я пропустил, где вы считали, что это будет не-op. Не это. Оба будут делать то же самое на машине LE; отмените порядок байтов. ntohl()
ожидает, что вы ntohl()
ему сетевой байт, заказанный int
Ответ 4
В вашей программе, когда вы пишете int a;
вы знаете, что a
содержит целое число, назначенное хостом, программа этого не знает. Вы могли бы легко предоставить int, уже содержащий значение в сетевом порядке. Конечно, если вы используете какой-либо арифметический оператор для значения, которое не находится в порядке хоста, результат будет неверным с точки зрения сети, если порядок сети не совпадает с порядком хоста.
Но это не так уж и хорошо, сетевые упорядоченные значения часто сохраняются именно таким образом в структурах низкого уровня, перед отправкой или только после их получения.
Что не так с вашей программой, так это то, что когда вы вызываете ntohl()
вы ntohl()
функцию ntohl()
которую вы предоставляете int
, - это некоторое значение, хранящееся в памяти в сетевом порядке. Это договор. Если это не так, функция не будет выполнять то, что вы ожидаете, и это то, что вы делаете.
Как и другие объяснения в большинстве систем (больших или маленьких, но не глупых-endians), две функции обычно идентичны, либо байтовые обратные, либо нет-op.