Little Endian中的ntohl()vs htonl()

Sub*_*esh 2 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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

 Network - 0x11223344   
 Host    - 0x11223344  
Run Code Online (Sandbox Code Playgroud)

这里htonl(0x44332211)=>我正在将小端(LE)转换为BE.所以输出会是0x11223344.我明白了.我的问题是ntoh().现在ntohl(0x44332211)=>什么?

这里我在1终端上执行两个命令.所以主机到网络,即hton()意味着我的终端到网络.那讲得通.但这里ntohl()意味着什么?ntohl()如果我们有:

a PC A----(ie hton)sending data over network------>(ie ntoh) to PC B?
Run Code Online (Sandbox Code Playgroud)

ntoh期望网络字节顺序即大端.请详细说明ntohl()上面的内容以及为什么它的打印相同0x11223344,为什么不0x44332211呢?

Jer*_*ner 11

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

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

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

这些函数的预期使用模式是这样的:

  • 无论何时您要向网络发送长信息,请在其上调用htonl()并发送该值.
  • 只要您刚收到网络中的长信,请在其上调用ntohl()并使用该值代替.

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


use*_*708 9

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

< netinet/in.h >

#  if __BYTE_ORDER == __LITTLE_ENDIAN
#define ntohl(x)     __bswap_32 (x)
#define htonl(x)     __bswap_32 (x)
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

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

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