程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> socket編程:字節序,socket字節序

socket編程:字節序,socket字節序

編輯:關於C語言

socket編程:字節序,socket字節序


接觸到socket編程,就一定會接觸字節序轉換。

對於字符串來說,是沒有字節序的差別的,就像我們寫字,內存就像是紙,字符串就從左向右依次寫:

內存地址:00000000 00000001 00000002 00000003 ...

內存數據:     'A'            'B'            'C'            'D'

而任何cpu讀取的時候,也都是從左向右依次讀取。

 

對於多字節數據(比如short、int、long...),不同字節序是有差別的。

所有x86架構cpu(包括x64)都是用的小端字節序,網絡字節序是大端序:

int a = 0x01020304;

內存地址:00000000 00000001 00000002 00000003 ...

大端序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) {
    int test = 0x12345678;
    char *p = (char *)&p;

    if(*p = 0x12)
        return 1;
    else
        return 0;
}

函數雖然簡陋,但是已經夠用了。

 

字節序轉換宏,順便將數字轉換成數組:

#define rhton16(h, n) {(n)[0]=((unsigned short)(h))>>8; (n)[1]=((unsigned short)(h))<<8>>8;}
#define rhton32(h, n) {(n)[0]=((unsigned int)(h))>>24; (n)[1]=((unsigned int)(h))<<8>>24; (n)[2]=((unsigned int)(h))<<16>>24; (n)[3]=((unsigned int)(h))<<24>>24;}
#define rhton64(h, n) {(n)[0]=((unsigned long)(h))>>56; (n)[1]=((unsigned long)(h))<<8>>56; (n)[2]=((unsigned long)(h))<<16>>56; (n)[3]=((unsigned long)(h))<<24>>56; (n)[4]=((unsigned long)(h))<<32>>56; (n)[5]=((unsigned long)(h))<<40>>56; (n)[6]=((unsigned long)(h))<<48>>56; (n)[7]=((unsigned long)(h))<<56>>56;}

數組轉換成數字:

#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))

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved