● 字節序的定義
字節序,顧名思義字節的順序,再多說兩句就是大於一個字節的數據在內存中的存放順序(一個字節的數據當然就無需談順序的問題)。
在大部分的開發中我們不需要考慮字節序的問題。唯有在跨平台以及網絡程序應用中字節序才是一個應該被考慮的問題。
● 網絡應用的字節序
網絡字節序是TCP/IP規定好的一種數據表示格式,它與具體的CPU類型、操作系統無關,從而可以保證數據在不同主機之間傳輸時能被正確解釋。網絡字節順序采用big endian排序方式。
在網絡編程時,並不是什么時候都要考慮字節序問題。那么什么時候需要考慮呢?
Intel CPU使用的都是little endian。
實際上如果是應用層的數據,即對TCP/IP來說是透明的數據,不用考慮字節序的問題。因為接收端收到的順序是和發送端一致的。
但對於TCP/IP關心的數據(IP地址、端口)來說就不一樣了。
例如我指定了一個端口號:
unsigned short port = 0x0012 (十進制18)
把這個端口號傳個TCP/IP建立一個socket連接。
sockaddr_in addr;
addr.sin_family = AF_INET; //使用互聯網際協議,即IP協議
addr.sin_port = port;
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
因為網絡字節序是big endian,即低地址存放的是數值的高位,所以TCP/IP實際上把這個port解釋為0x1200(十進制4608)。本來打算是要在端口18建立連接的,但TCP/IP協議棧卻在端口4608建立了連接。
當一個數據是應用層和TCP/IP都需要關心的時候,需要考慮這個數據的字節序(一般而言就是IP地址和端口號)。
我覺得網絡字節序的問題其實可以隱藏在TCP/IP中的,不知道為什么沒有那么做?
● 字節序轉換函數
htons 把 unsigned short 類型從主機序轉換到網絡序
htonl 把 unsigned long 類型從主機序轉換到網絡序
ntohs 把 unsigned short 類型從網絡序轉換到主機序
ntohl 把 unsigned long 類型從網絡序轉換到主機序
這幾個函數很好記,比如htons中hton代表host to network, s代表unsigned short
char FAR * inet_ntoa( struct in_addr in);
將一個IP轉換成一個互聯網標准點分格式的字符串。
in_addr_t inet_addr(const char *cp);
將一個點分十進制的IP轉換成一個長整數型數(u_long類型)。返回值已是網絡字節順序,可以直接作為internet 地址