關於socket通信中大小端轉換問題


本人一直有個疑惑,大小端通信怎么存儲(以前一直知道這個概念,但怎么都跟實際匹配不上,網絡上也並沒有說怎么處理大小端通信問題)

socket通信中 addr 需要轉換成網絡字節序,也就是大端

助記: htonl h-> host 縮寫 n -> net 縮寫 l 是類型縮寫(l -> long  ll-> longlong s short 都是無符號的)

首先理解下,大小端  數據在內存的存儲順序不同,注意數據還是那個數據只是存儲的方式不同

大端,數據的低位在內存的高位

小端,數據的低位在內存的低位

內存地址是按字節排序的 0x01 0x02 每個地址偏移是一個字節的內容。

數據 0x12345678  數據的從低到高 0x78 0x56 0x34 0x12.

大端 內存內數據 0x01-0x12 0x02-0x34 0x03-0x56 0x04-0x78

小端 內存內數據 0x01-0x78 0x02-0x56 0x03-0x34 0x04-0x12

socket傳輸的是字節流,byte[] 數組,我們分兩種情況討論 unsigned int var=0x12345678; 在網絡中的傳輸狀態。

1.兩端 大小端 一致,則直接使用memcpy就可以,memcpy是內存數據的 大端會變成 0x12345678 數據傳輸到對端,把數據copy到內存中也是 0x12345678, 小端是 0x78563412, copy 到本地 也是這個值,毫無影響。

2.兩端 大小端 不一致,變成byte數據的時候,memcpy是內存數據的 大端會變成 0x12345678 數據傳輸到對端,把數據copy到內存中也是 0x12345678,  這時cpu按內存地址認為值的話, 並不等於 數據0x12345678. 所以解析錯誤。小端同理。

解決辦法,所以在socket傳輸多字節數據的情況下,需要把內存數據轉為數據順序(自定義的,可以從高到低,也可以從低到高,但是發送端和解析端必須一致)

比如說

void writeInt32(int v) {
    char buf[4] = {};
    buf[0] = (v >> 24) & 0xFF;
    buf[1] = (v >> 16) & 0xFF;
    buf[2] = (v >> 8) & 0xFF;
    buf[3] = (v >> 0) & 0xFF;
}
int readInt32(char[] buf) {
    int ch1 = buf[0];
    int ch2 = buf[1];
    int ch3 = buf[2];
    int ch4 = buf[3];
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

上述這樣操作,即可解決對應的字節流傳輸大小端問題。

題話外:

java 的數據類型都是大端,float 都是iee那個標准,也可以這種傳輸。

當然有更好的解決辦法,用protobuf,protobuf數據里面就做了這種事情。

另外本地數據如果用memcpy存儲到本地,不做這種處理的話,也會出現當前問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM