1. 程式人生 > 其它 >[轉載+翻譯]java 關於主機位元組序(host byte order)和網路位元組序(network byte order)

[轉載+翻譯]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_家族不會在網路上傳送出去,所以它可以按主機位元組順序傳送。