接觸到socket程式設計,就一定會接觸位元組序轉換。
對於字串來說,是沒有位元組序的差別的,就像我們寫字,記憶體就像是紙,字串就從左向右依次寫:
記憶體資料: 'a' 'b' 'c' 'd'
而任何cpu讀取的時候,也都是從左向右依次讀取。
對於多位元組資料(比如short、int、long...),不同位元組序是有差別的。
所有x86架構cpu(包括x64)都是用的小端位元組序,網路位元組序是大端序:
int a = 0x01020304;
大端序a : 0x01 0x02 0x03 0x04 即cpu讀出的資料從高向低位寫入變數
小端序a : 0x04 0x03 0x02 0x01 即cpu讀出的資料從低向高位寫入變數
如果我們寫的程式不進行位元組序轉換會怎麼樣呢:
int a = 0x01020304;
在我們x86架構機器的記憶體裡,它是這樣寫的0x04030201(注意,這是它在記憶體裡的真實寫法,當我們的程式以int型讀取的時候才會轉化成0x01020304),此時進行網路傳送,send程式會以位元組的方式(可以把它想象成字串),一位元組一位元組的傳送,到了網路上,它的順序仍然是0x04030201(此時它的順序已經錯了)。當資料到達對端機器的時候,對端機器也是一位元組一位元組的收入記憶體,它的順序仍然是0x04030201。如果對端仍是x86架構,那麼資料讀出來的時候它又被轉化成了0x01020304,這看起來像是對的。但是如果對端是大端序的架構,那麼它的int型資料就變成了0x04030201。
位元組序轉換:
linux裡提供了現成的函式:htonl, ntohl ... 這是一系列函式,卻只提供了2位元組和4位元組的轉換。
判斷位元組序:
int is_big_endian(void)
函式雖然簡陋,但是已經夠用了。
位元組序轉換巨集,順便將數字轉換成陣列:
#define rhton16(h, n)
#define rhton32(h, n)
#define rhton64(h, n)
陣列轉換成數字:
#define rntoh16(n) (((unsigned short)((n)[1])) | ((unsigned short)((n)[0])<<8))
#define rntoh32(n) (((unsigned int)((n)[3])) | ((unsigned int)((n)[2])<<8) | ((unsigned int)((n)[1])<<16) | ((unsigned int)((n)[0])<<24))
#define rntoh64(n) (((unsigned long)((n)[7])) | ((unsigned long)((n)[6])<<8) | ((unsigned long)((n)[5])<<16) | ((unsigned long)((n)[4])<<24) | ((unsigned long)((n)[3])<<32) | ((unsigned long)((n)[2])<<40) | ((unsigned long)((n)[1])<<48) | ((unsigned long)((n)[0])<<56))
socket程式設計之網路位元組序與主機位元組序
0 為什麼會有大小端模式之分呢?這是因為在計算機系統中,我們是以位元組為單位的,每個位址單元都對應著乙個位元組,乙個位元組為 8bit。但是在c語言中除了8bit的char之外,還有16bit的short型,32bit的long型,另外,對於位數大於 8位的處理器,例如16位或者32位的處理器,由於...
網路程式設計 位元組序
三 位址形式的轉換函式 當儲存多位元組資料時,就涉及到位元組序的概念。高位位元組儲存在低位址為大端對齊,低位位元組儲存在低位址為小端對齊。判斷系統為大端對齊還是小端對齊的方法 include typedef union data intmain int argc,char ar else if ob...
大端位元組序 小端位元組序(網路位元組序 主機位元組序)
大端位元組序 整數的高位位元組儲存在記憶體的低位址處,低位元組儲存在記憶體的高位址處。一般pc大多採用小端位元組序,也稱為主機位元組序。網路上傳輸採用大端位元組序,也稱為網路位元組序。linux中常用轉換函式如下 include uint32 t htonl uint32 t hostlong 無符...