为什么通过网络发送的数据转换为网络字节顺序?

时间:2013-04-07 06:03:19

标签: c sockets ipc

我不确定如何使用hton()。理论上,通过网络发送的任何数据都应采用网络字节(即大端)格式。假设客户端A支持big-endian而B支持little-endian。我正在从A发送数据到B,数据被读取为多字节。然后在网络中,我们需要使用htonl()htons()将数据转换为网络字节顺序。由于客户端A已经是big-endian,htonl()htons()会返回相同的输出。但是B是小端的,所以这些功能颠倒了顺序。鉴于此,我们怎么能说当大端和小端机器需要通信时,坚持使用通用格式(即大端)是解决问题的方法?

2 个答案:

答案 0 :(得分:7)

我会以另一种方式尝试,显示整个流程:

通过电话发送0x44332211始终以44 33 22 11发送。发件人的htonl()通过恢复字节的顺序(在LE机器上)或者只是保留它们的方式(在BE机器上)来确保。接收方将44 33 22 11转换为0x44332211ntohl() - 再次通过还原或离开它们。

提到的函数{hton,ntoh}{l,s}()以可移植的方式帮助编程:无论程序是在LE还是BE机器上进行调整,它们始终按照应有的方式工作。因此,即使在BE机器上,也应该调用这些函数,即使它们是noops。

示例:

A(BE)希望将0x44332211发送给B(LE)。

  1. A在内存中的号码0x4433221144 33 22 11
  2. 调用htonl(),因为该程序已被编写为可移植。
  3. 该号码仍然表示为44 33 22 11并通过电汇发送。
  4. B收到44 33 22 11并通过ntohl()
  5. B从11 22 33 44获取ntohl()所代表的值,并将其放入相应的变量中,然后根据需要生成0x44332211
  6. 同样,总是调用这些函数的需求使您无需考虑编写哪种类型的机器 - 只需编程所有种类的机器,并在需要时调用这些机器中的每一种

    可以在不知道A或B是BE还是LE的情况下表达相同的示例:

    1. A的内存编号为0x44332211
    2. 拨打htonl(),以便号码通过网络发送为44 33 22 11。 是通过还原还是通过保留来完成,取决于主机B的字节顺序。
    3. B收到44 33 22 11并将其通过ntohl()。这个是否反转,取决于主机B的字节顺序。
    4. B获得所需的值0x44332211

答案 1 :(得分:1)

我认为你认为客户B看到“逆序”中的字节意味着他们错了。与客户端A相比,字节的顺序相反,但这是因为客户端A从客户端B向后解释整数;两者仍将最终解释为相同的数字。例如,一台机器将数字4表示为00 00 00 04。另一个将其表示为04 00 00 00,但两者仍然会将其视为4 - 如果您向其添加1,则您将分别获得00 00 00 0505 00 00 00。存在hton / ntoh函数,因为无法查看数字并知道它是大端还是小端,因此接收器无法确定解释字节的方式