[转载+翻译]java 关于主机字节序(host byte order)和网络字节序(network byte order)


英文来源:https://blog.csdn.net/weixin_36155560/article/details/114567096

转载原因:需要将Myo接收IMU数据的16bit short UUID转为full 128bit UUID,它的顺序依赖于network order

原文(原出处排版不太好):

For those who are new to sockets programming or who've long ago forgotten the idiosyncrasies of byte ordering with sockets (as I had when I needed to know this last year),here's a primer on what byte ordering is,why it's needed, and terms such as little-endian, big-endian, network byte order, and host bye order. The main benefit of the sockets programming interface is that it enables you to communicate with other systems over a network—regardless of their processor or operating system. The sockets programming interface is similar across modern operating systems; as a result, you might end up communicating with machines that interpret and store data in completely incompatible ways. For example, Intel and VAX machines store numeric values in least significant byte first order. This ordering of bytes is known as little-endian because the data is represented "little-end-first."
On the other hand, workstations—such as most Unix workstations—store numeric with the most significant byte first—or big-endian for "big-end-first."
As an example, Table 1 shows the differences between representing the decimal value 256 would be seen in the hex display of a debugger in little-endian and big-endian formats.

Table 1—Formatting of the decimal value 256 in little-endian and big-endian.

Format Hex
Value
Little-Endian  00 01
Big-Endian  01 00

For example, if you send the number 256 in big-endian format to another system that interprets numbers in little-endian format, the receiving system would misinterpret the number as decimal one instead of decimal 256.

Because of these differences, the Internet Protocol Suite defines two terms—network byte order and host byte order. Network byte order is a format where the most significant byte is first. Host byte order refers to the local machine's byte order. Note that the host byte order could be either little-endian or big-endian, depending on the local machine's processor (Intel, HP, Motorola, etc.) Also, the host order may or may not be the same as the network order. However, if there's the chance that your code could run on a different type of machine than the one you're developing on and to ensure that the data is interpreted correctly, you should always convert from host to network byte order when sending data and from network to host byte order when receiving data.

Convert the Natives!

We've now been lead right into the next section. There's been too much talk about this Network to Host Byte Order conversion--now is the time for action!
All righty. There are two types that you can convert: short (two bytes) and long (four bytes). These functions work for the unsigned variations as well. Say you want to convert a short from Host Byte Order to Network Byte Order. Start with "h" for "host", follow it with "to", then "n" for "network", and "s" for "short": h-to-n-s, or htons() (read: "Host to Network Short"). It's almost too easy...You can use every combination of "n", "h", "s", and "l" you want, not counting the really stupid ones. For example, there is NOT a stolh() ("Short to Long Host") function--not at this party, anyway.

But there are:
htons() -- "Host to Network Short"
htonl() -- "Host to Network Long"
ntohs() -- "Network to Host Short"
ntohl() -- "Network to Host Long"

Now, you may think you're wising up to this. You might think, "What do I do if I have to change byte order on a char?" Then you might think, "Uh, never mind." You might also think that since your 68000 machine already uses network byte order, you don't have to call htonl() on your IP addresses. You would be right, BUT if you try to port to a machine that has reverse network byte order, your program will fail. Be portable! This is a Unix world! (As much as Bill Gates would like to think otherwise.) Remember: put your bytes in Network Byte Order before you put them on the network.

A final point: why do sin_addr and sin_port need to be in Network Byte Order in a struct sockaddr_in, but sin_family does not? The answer: sin_addr and sin_port get encapsulated in the packet at the IP and UDP layers, respectively. Thus, they must be in Network Byte Order. However, the sin_family field is only used by the kernel to determine what type of address the structure contains, so it must be in Host Byte Order. Also, since sin_family does not get sent out on the network, it can be in Host Byte Order.

翻译:

对于那些刚刚接触sockets编程的人,或者很久以前就忘记了sockets字节排序的特性的人(就像我去年需要了解这一点时所做的那样),这里有一本关于字节排序是什么、为什么需要字节排序以及诸如小端、大端、网络字节顺序和主机字节顺序等术语的入门书。sockets编程接口的主要优点是,它使您能够通过网络与其他系统通信,而不管它们的处理器或操作系统如何。sockets编程接口在现代操作系统中是相似的;因此,您可能最终会与以完全不兼容的方式解释和存储数据的计算机通信。例如,英特尔和VAX机器以最低有效字节的第一顺序存储数值。这种字节顺序被称为little endian(低位编址,后称小端),因为数据表示为“little end first”。另一方面,像大多数Unix工作站这样的工作站存储以最高有效字节为第一位的数字或“大端优先”的big-endian(高位编址,后称大端)
例如,表1显示了以小端和大端格式在调试器的十六进制显示中表示十进制值256的差异。

表1-小端和大端十进制值256的格式。

十六进制格式

小端 00 01
大端 01 00
例如,如果将大端格式的数字256发送给另一个以小端格式解释数字的系统,接收系统会将该数字错误地解释为十进制数字,而不是十进制256。

由于这些差异,Internet协议套件定义了两个术语:网络字节顺序和主机字节顺序。网络字节顺序是最高有效字节位于第一位的格式。主机字节顺序是指本地机器的字节顺序。请注意,主机字节顺序可以是little endian或big endian,具体取决于本地计算机的处理器(英特尔、惠普、摩托罗拉等)。此外,主机顺序可能与网络顺序相同,也可能不同。但是,如果您的代码可能运行在不同于您正在开发的机器类型的机器上,并且为了确保正确解释数据,您应该始终在发送数据时从主机字节顺序转换为网络字节顺序,在接收数据时从网络字节顺序转换为主机字节顺序。
主客互换!
我们现在直接进入下一节。关于网络到主机字节顺序转换的讨论太多了——现在是采取行动的时候了!
好的。有两种类型可以转换:短(两个字节)和长(四个字节)。这些函数也适用于无符号变体。假设您想将短消息从主机字节顺序转换为网络字节顺序。以“h”开头表示“主机”,然后以“to”开头,然后以“n”表示“网络”,以“s”表示“短”:h-to-n-s,或htons()(读作:“主机到网络短”)。这太容易了。。。你可以使用你想要的“n”、“h”、“s”和“l”的每一个组合,而不是真正愚蠢的组合。例如,没有stolh()(“Short to Long Host”)函数——无论如何,在这里没有。

但有:
htons()--“主机到网络短路”
htonl()--“主机到网络长”
ntohs()--“网络到主机短路”
ntohl()--“网络到主机长”

现在,你可能会认为你在做这件事。你可能会想,“如果我必须改变字符的字节顺序,我该怎么办?”然后你可能会想,“呃,没关系。”您可能还认为,因为您的68000机器已经使用网络字节顺序,所以您不必在IP地址上调用htonl()。你是对的,但如果你试图把端口连接到一台网络字节顺序相反的机器上,你的程序就会失败。随身携带!这是一个Unix世界!(正如比尔·盖茨所希望的那样。)记住:在将字节放到网络上之前,先将它们按网络字节顺序排列。

最后一点:为什么sin_addr和sin_port在结构sockaddr_in中需要按网络字节顺序排列,而sin_family不需要?答案是:sin_addr和sin_port分别封装在IP和UDP层的数据包中。因此,它们必须按网络字节顺序排列。然而,sin_family字段仅由内核用于确定结构包含的地址类型,因此它必须按主机字节顺序。此外,由于sin_家族不会在网络上发送出去,所以它可以按主机字节顺序发送。