Little Endian下的ntohl()和htonl()的区别

6

请帮我澄清疑惑,因为以下内容让我感到非常困惑,而且在网上找不到一个清晰的答案。

#include<stdio.h>
int main()
{
   int a = 0x44332211;
   printf("Network - 0x%x\n", htonl(a));// Host to network
   printf("Host    - 0x%x\n", ntohl(a));// Network to host
   return 0;
}

输出:

 Network - 0x11223344   
 Host    - 0x11223344  

这里,htonl(0x44332211)意味着将小端序(LE)转换为大端序(BE)。所以输出结果将是0x11223344。我明白了这一点。我的问题是关于ntoh()的问题。现在 ntohl(0x44332211)的输出是什么?

我在一个终端上执行了这两个命令。所以,主机到网络即hton()意味着从我的终端到网络的转换。这很有道理。但是,ntohl()的含义是什么?只有当我们有:

a PC A----(ie hton)sending data over network------>(ie ntoh) to PC B?

此外,ntohl()期望网络字节序即大端字节序。请解释为什么它的输出与0x11223344相同,而不是0x44332211
2个回答

17
假设您的程序在小端机器上运行(例如x86),ntohl(a)将返回0x11223344(即它将翻转0x11223344值的字节顺序,就像htonl()一样)。
另一方面,如果您的程序在大端机器上运行(例如PowerPC Mac),那么ntohl(a)和htonl(a)都将直接返回a,因为机器的内部/主机格式已经与网络格式相同。
还有一种(至少理论上的)可能性是,您的程序正在运行在某些使用既不是大端也不是小端的数字表示的非常规硬件上。在这种情况下,该环境的htonl()和ntohl()函数将被编程为执行正确的操作(无论那是什么)以将该机器的内部表示转换为标准网络表示(即大端)并进行反向转换。
这些函数的预期使用模式如下:
  • 每当您要将长整型数据发送到网络时,请调用 htonl() 函数并发送该值。
  • 每当您从网络接收到长整型数据时,请调用 ntohl() 函数并使用该值。

这样一来,主机计算机的数字表示形式和网络/大端表示形式之间的任何差异都会在 htonl() 和 ntohl() 函数内自动处理,您不必担心为程序可能在的每个计算机架构编写(和测试!)单独的转换代码。


12

刚刚偶然看到这篇文章。我同意Jeremy的回答,但是想再添加一点: 在怀疑时,请查看源代码。如果您查看GCC库中ntoh()和hton()的定义:

<netinet/in.h></p>

#  if __BYTE_ORDER == __LITTLE_ENDIAN
#define ntohl(x)     __bswap_32 (x)
#define htonl(x)     __bswap_32 (x)
#endif

因此,ntohl()和htonl()只是在byteswap.h中定义的字节交换。这就是为什么这两个宏的输出相同的原因。

现在问题来了,他们为什么相同呢? 嗯,作者打算让ntohl()在网络端数据(通常是接收到的数据包缓冲区的内容)上调用,类似地,让htonl()在主机端数据(由主机编写的数据)上调用。

在您的情况下,您将这两个宏都用于相同的主机端数据,这就是问题所在。

我回复晚了,但希望下一个访客会发现这个答案有用 :)


1
请注意,定义和头文件是特定于架构的。如果您查看为在自己的计算机上本地编译代码安装的头文件,则只会查看GCC源代码的一小部分子集! - binki
在一个只有大端和小端两种格式的世界中,切换这两种格式总是一个简单的字节级数组反转。反转数组的逆操作就是反转数组(同一操作)。因此,没有必要同时拥有 ntoh*()hton*()。重要的是 API 支持主机字节顺序既不是大端也不是小端的情况,这种情况下转换的逆操作可能与转换本身不同。 - binki
术语“大端和小端”直接来自DARPA备忘录,描述了字节顺序。这是一份值得阅读的文件,因为它包含了许多对现在已经过时的架构的引用:https://www.rfc-editor.org/ien/ien137.txt然而,所有这些架构都具有这样的特性,即无论它们采用何种混合顺序,ntoh*()和hton*()始终只会交换元素,因此它们是相同的;目前没有已知的架构,例如通过将32位字左移8位来达到网络字节顺序,然后再将其右移8位来恢复主机顺序。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接