1. 程式人生 > >關於c# 大端序 java 小端序的理解

關於c# 大端序 java 小端序的理解

為了理解網路socket解析請求訊息頭部的過程,今天把c#和java的記憶體結構學習了一下,主要是讀取二進位制資料的區別,這是個非常值得注意的問題,如果你不使用string自帶的解析介面的話。
現在假設請求物件維護瞭如下的結構:

    /// +-------+---+-------------------------------+
    /// |request| l |                               |
    /// | name  | e |    request body               |
    /// |  (5)  | n |                               |
/// | |(2)| | /// +-------+---+-------------------------------+ /// request name: the name of the request, 4 chars, used for matching the processing command /// len: the lenght of request data, two bytes, 0x00 0x02 = 2, 0x01 0x01 = 257 /// request data: the body of the request

請求的key佔了5個位元組,如果要獲取請求體的長度,應該從第6個位元組開始讀。問題來了,已知這個請求物件在接收包的位置偏移是offset(位元組),怎麼從記憶體中讀取len這個值?
首先,我們來看一個例子,如果一個16進位制的值在記憶體中怎麼存:
你使用c#是小端序的,也就是說低位對低地址,俗稱小對小
0X02|0X02|
0X01|0X01|
以上是小端序的記憶體結構
值讀出來就是2*2^8+1*2^0,0X02 0X01
在java 是大端序,也就是說高位對低地址,俗稱大對小
0X02|0X01|
0X01|0X02|
以上是大端序的記憶體結構
值讀出來就是1*2^8+2*2^0,0X01 0X02,如果從網路上獲取資料解析成二進位制陣列的時候就要注意高位和低位的順序,不然就會出現如上的差(錯)別(誤)。
所以對於寫c#的童鞋,GetBodyLengthFromHeader()函式應該這樣寫

protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
        {//!!!!!!!!!!!!!!C#小端序!!!!!!!!!!!!!!!
           // int dataLen = header.ToInt(offset + 4);
            int dataLen = (int)header[offset + 5] * 256 + (int)header[offset + 6];
            //Console.WriteLine("data length:" + dataLen.ToString());
            return dataLen;
        }

如果想要自動將端序改為網路公用的(大端序),可以用函式HostToNetworkOrder獲取

int bigend_a = IPAddress.HostToNetworkOrder(lowend_a)

接下來就不用你去關心c#接收網路資料或者java處理後的資料高低位轉換問題了。