socket編程:位元組序

來源:互聯網
上載者:User

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

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.