通訊端與網路程式設計

位元組順序(byte order)

把一千二百三十四寫成 1234,每個人讀法都一樣。但電腦把多位元組的數字存成一串位元組,而對於哪個位元組要擺前面,存在真正的歧見。位元組順序,或稱端序(endianness),是機器把數字的位元組排進記憶體所用的規則:大端序(big-endian)把最高有效位元組擺前面(「大的那端」),小端序(little-endian)把最低有效位元組擺前面。

拿 16 位元的數字 0x1234 來說。大端序機器把它存成位元組 0x12、0x34;小端序機器存成 0x34、0x12——同一個值、位元組相反。這在兩台電腦交換二進位數字的那一刻就要緊,因為若小端序發送端的 0x34、0x12 被大端序接收端照原樣讀取,就變成 0x3412,一個完全錯誤的數字。為避免亂套,網際網路協定約定了一種慣例,叫做網路位元組順序(network byte order),也就是大端序。所以在把連接埠號或長度欄位放上線路之前,你要從主機順序轉成網路順序,收到時再轉回來。

為什麼重要:這是網路與二進位格式程式碼中真實又常見的臭蟲,而通訊端 API 正為此給了你輔助函式:htons(host-to-network short,給連接埠這類 16 位元值)、htonl(host-to-network long,32 位元),以及反向的 ntohs 與 ntohl。你在把連接埠號傳給 bind 或 connect 之前對它用 htons。在小端序機器(今日多數 x86 與 ARM)上,這些函式會交換位元組;在大端序機器上它們什麼都不做——這正是為什麼你該總是呼叫它們、而非假設,好讓同一份程式碼到處都正確。要注意,HTTP 這類文字協定把數字當成人類可讀的數字送出,繞過了這件事,那裡不適用位元組順序。

要綁定到 8080 埠,你寫 addr.sin_port = htons(8080)。在小端序筆電上 htons 翻轉那兩個位元組,使 8080 以大端序上線路;在大端序機器上它原封不動。無論哪種,接收端用 ntohs 讀到的都是 8080——而不是錯亂的值。

永遠用 htons/htonl 轉換——別假設你機器的順序。

對連接埠忘記 htons 是經典臭蟲,常在沒有大端序的環境下藏起來:程式碼在一台機器上看似沒事、到另一台就壞。呼叫轉換函式能讓同一份原始碼在每種架構上都正確。

又称
endiannessbig-endianlittle-endiannetwork byte order位元組序端序