3

请澄清我的疑问,因为我对以下内容感到非常困惑,而且我在网上的任何其他地方都找不到干净的答案。

#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)=> 什么?

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

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

ntoh需要一个网络字节顺序,即大端。请解释ntohl()上面的意思以及为什么它的打印与打印相同0x11223344,为什么不打印0x44332211

4

2 回答 2

13

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

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

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

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

  • 每当您要向网络发送 long 时,请在其上调用 htonl() 并发送该值。
  • 每当您刚刚从网络收到一个 long 时,请在其上调用 ntohl() 并改用该值。

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

于 2013-04-07T16:38:25.173 回答
11

刚刚偶然发现这个帖子。我同意 Jeremy 的回答,但只想再补充一点:如有疑问,请转到源代码。如果您查看 GCC 库中的 ntoh() 和 hton() 定义:

<网/in.h >

#  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 数据上调用这两个宏,这就是问题所在。

我想我迟到了。但是,我希望下一位访问者会发现这个答案很有用:)

于 2015-07-02T00:43:12.097 回答