小端的ntohl()vs htonl()

时间:2013-04-07 14:58:21

标签: c endianness htonl

请澄清我的疑问,因为我对下面的东西感到困惑,我无法得到一个     在网上的任何其他地方清理anwser。

#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) =&gt;我正在将小端(LE)转换为BE。因此输出将为0x11223344。我明白了。我的问题在于ntoh()。现在ntohl(0x44332211) =&gt;什么?

这里我正在1终端上执行两个命令。所以托管到网络,即hton()意味着我的网络终端。那讲得通。但这里ntohl()意味着什么?如果我们有:{/ p>,ntohl()就会出现

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

同样ntoh期望网络字节顺序,即大端。请注意上面ntohl()的含义以及为什么它与0x11223344打印相同,为什么不打0x44332211

2 个答案:

答案 0 :(得分:11)

假设您的程序在小端机器上运行(例如x86),ntohl(a)将返回0x11223344(即它将翻转0x11223344值的字节顺序,就像htonl()一样)。

另一方面,如果你的程序在大端机器(例如PowerPC Mac)上运行,那么ntohl(a)和htonl(a)都将返回a,逐字,因为机器的内部/主机格式已经与网络格式相同。

还有一种(至少理论上的)可能性,你的程序运行在一些unusual hardware上,它使用的数字表示既不是big-endian也不是little-endian。在这种情况下,该环境的htonl()和ntohl()函数将被编程为执行正确的操作(无论可能是什么)将该机器的内部表示转换为标准网络表示(这是大端)和回来。

这些功能的预期使用模式是:

  • 无论何时你想要向网络发送一个长信息,请在其上调用htonl()并发送该值。
  • 任何时候你刚从网络上收到一个长途,请在其上调用ntohl()并使用该值代替。

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

答案 1 :(得分:9)

偶然发现了这篇文章。我同意Jeremy的回答,但只是想补充一点: 如有疑问,请转到源代码。如果你看一下GCC库中的ntoh()和hton()定义:

&LT; netinet/in.h&GT;

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

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

现在,他们为什么一样? 好吧,作者希望在网络端数据(通常是接收数据包缓冲区的内容)上调用ntohl(),类似地,在主机端数据(主机写入的数据)上调用htonl()。

在您的情况下,您在相同的Host Endian数据上调用这两个宏,这就是问题所在。

猜猜我迟到了回复。但是,我希望下一位访客发现这个答案很有用:)