htonl()和ntohl()在整数上的输出相同
我在little-endian [LE]机器[Linux,Intel处理器]上运行了以下程序。 我无法在下面的代码片段中解释3个输出。 由于机器是LE,a的值存储为0x78563412
。 打印时,它显示其实际值。 由于它是LE机器,我希望ntohl()
成为无操作并显示0x78563412
,它正在做。 但是,对于包含htonl()
第二个print语句,我期望0x12345678
。 有人可以帮我理解他们为什么一样吗?
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
由于它是LE机器,我希望
ntohl()
成为无操作
那是错误的。 网络字节顺序为big-endian ,主机字节顺序为little-endian。 因此, ntohl
和htonl
返回其输入的字节交换版本。
记住, htonl
是你可以在主机上取一个整数,然后写:
int i = htonl(a);
结果是, 当使用网络字节顺序解释时 , i
的存储器具有与a相同的值。 因此,如果将对象表示forms写入套接字并且另一端的阅读器需要网络字节顺序的4字节整数,则它将读取a的值。
并显示
0x78563412
这是你打算写的吗? 如果ntohl
是无操作(或者更确切地说是一个身份函数),那么你的第三行必然会打印与第一行相同的东西,因为你会有ntohl(a) == a
。 这是在big-endian实现上发生的事情,程序打印:
Original - 0x12345678 Network - 0x12345678 Host - 0x12345678
htonl
和ntohl
的function完全相同。 他们应该满足htonl(ntohl(x)) == x
。 它们的名称不同,仅用于文档(您明确表示要从主机到网络或其他方式进行转换,即使它们是相同的)。 因此,在小端机器上,它们都执行字节交换,而在大端机器上,它们都是无操作的。
因为您传递的a
by值,因此它们不会被这些函数中的任何一个更改。
你正在打印htonl()
和ntohl()
返回的内容 。
编辑添加:我错过了你认为一个无操作的地方。 不是。 两者都将在LE机器上做同样的事情; 反转字节排序。 ntohl()
希望你传递一个网络字节有序的int
在你编写int a;
你知道a
包含一个主机有序整数,程序不知道。 您可以轻松地提供已经包含网络顺序值的int。 当然,如果对非主机顺序的值使用任何算术运算符,如果网络顺序与主机顺序不同,则从网络角度来看结果将是不正确的。
但这并不是那么遥远,网络有序值通常在低级结构中保持这种方式,在发送之前或刚接收之后。
您的程序有什么问题,当您调用ntohl()
您承诺使用ntohl()
函数,您提供的int
是按网络顺序存储在内存中的某些值。 这是合同。 如果不是这样,该function将无法执行您所期望的function,这就是您所看到的。
正如大多数系统(大或小但不是愚蠢的端)所解释的那样,这两个函数通常是相同的,无论是字节反转还是无操作。