網絡通信是按照字節流進行數據交換的,主機根據不同的CPU型號可能是大段存儲,也可能是小端存儲。而網絡字節序在TCP/IP協議中已經規定好了,采用大端的排序方式。
所以網絡通信中一般將需要傳輸的整數型值轉換成網絡字節序。
從本機字節序轉換成網絡字節序:host to net short/long
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
從網絡字節序轉換成本機字節序:
#include <arpa/inet.h>
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netlshort);
轉換的原理其實也很簡單,就是判斷一下本地是大端還是小端,是大端就轉換一下序列,否則啥都不干。
下面介紹兩種用來判斷大小端的方法:
第一種,使用union
大端是指低字節存儲在高地址;小端存儲是指低字節存儲在低地址。我們可以根據聯合體來判斷該系統是大端還是小端。因為聯合體變量總是從低地址存儲。
bool isNetByteOrder()
{union test {int i;char c;};test t;t.i = 1;// 如果是大端,則 t.c 為0x00,則 t.c != 1 返回true// 否則返回falsereturn (t.c != 1);
}
第二種,使用char指針
隨意找一個2字節的十六進制數值,如0x1234
如果本地是小端編碼,那么12存在高地址,34存在低地址。那么強行把0x1234轉換成1字節的char時,高字節會被丟棄,留下低字節值34。
如果本地是大端編碼,那么高地址字節種存儲的是34,12存在低地址,強制轉換成1字節的char時,高字節會被丟棄,留下低字節值12。
bool isNetByteOrder()
{unsigned short mode = 0x1234;char* pmode = (char*) &mode;// 如果將低字節放在低位,則是小端字節序return (*pmode != 0x34);
}
實現htons函數
uint16_t htons(uint16_t hostshort)
{if (isNetByteOrder())return hostshort;else return ((uint16_t)(hostshort >> 8)) | ((uint16_t)((hostshort & 0x00ff) << 8));
}