大小端及網絡字節序分析

大小端及網絡字節序分析

一、什麼是大端模式、小端模式

  1. 大端字節序(Big Endian):最高有效位存於最低內存地址處,最低有效位存於最高內存處;
  2. 小端字節序(Little Endian):最高有效位存於最高內存地址,最低有效位存於最低內存處。

二、Wireshark抓包分析大小端

小端:如下圖

小端示例
小端示例

即在抓包的時候顯示的數據是顛倒順序顯示的,即4字節的數值顯示的值是:0x01 0x00 0x00 0x00,但是實際的值是0x00 0x00 0x00 0x01即值爲1

大端:如下圖

大端示例
大端示例

即在抓包的時候顯示的數據是正常順序顯示的,即4字節的數值顯示的值是:0x00 0x00 0x10 0x00,實際值就是4096

三、網絡字節序

  網絡上傳輸的數據都是字節流,對於一個多字節數值,在進行網絡傳輸的時候,先傳遞哪個字節?也就是說,當接收端收到第一個字節的時候,它將這個字節作爲高位字節還是低位字節處理,是一個比較有意義的問題;

  UDP/TCP/IP協議規定:把接收到的第一個字節當作高位字節看待,這就要求發送端發送的第一個字節是高位字節;而在發送端發送數據時,發送的第一個字節是該數值在內存中的起始地址處對應的那個字節,也就是說,該數值在內存中的起始地址處對應的那個字節就是要發送的第一個高位字節(即:高位字節存放在低地址處);由此可見,多字節數值在發送之前,在內存中因該是以大端法存放的;

  所以說,網絡字節序是大端字節序;

  在實際中,當在兩個存儲方式不同的主機上傳輸時,需要藉助字節序轉換函數。

四、C#字節數據與數值的轉換

/// <summary>
/// byte字節數組轉int(大端)
/// </summary>
/// <param name="src">數據源</param>
/// <param name="offset">數據所在的偏移量</param>am>
/// <param name="len">要轉換的長度</par
/// <returns></returns>
public static int BytesToInt(byte[] src, int offset, int len)
{
    switch (len)
    {
        case 2:
            return (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        case 3:
            return (src[offset++] & 0xFF) << 16 |
                   (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        case 4:
            return (src[offset++] & 0xFF) << 24 |
                   (src[offset++] & 0xFF) << 16 |
                   (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        default:
            return 0;
    }
}

/// <summary>
/// int轉byte字節數組(大端)
/// </summary>
/// <param name="value">數值</param>
/// <param name="len">轉換的長度</param>
/// <returns></returns>
public static byte[] IntToBytes(int value, int len)
{
    byte[] src = new byte[len];
    switch (len)
    {
        case 1:
            src[0] = (byte)(value & 0xFF);
            break;
        case 2:
            src[0] = (byte)((value >> 8) & 0xFF);
            src[1] = (byte)(value & 0xFF);
            break;
        case 3:
            src[0] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);
            src[2] = (byte)(value & 0xFF);
            break;
        case 4:
            src[0] = (byte)((value >> 24) & 0xFF);
            src[1] = (byte)((value >> 16) & 0xFF);
            src[2] = (byte)((value >> 8) & 0xFF);
            src[3] = (byte)(value & 0xFF);
            break;
    }

    return src;
}

/// <summary>
/// int轉byte字節數組(小端)
/// </summary>
/// <param name="value">數值</param>
/// <param name="len">要轉換成字節數組的長度</param>
/// <returns></returns>
public static byte[] IntToBytesEx(int value, int len)
{
    byte[] src = new byte[len];
    switch (len)
    {
        case 1:
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 2:
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 3:
            src[2] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 4:
            src[3] = (byte)((value >> 24) & 0xFF);
            src[2] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
    }
    return src;
}

/// <summary>
/// byte字節數組轉int(小端)
/// </summary>
/// <param name="src"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public static int BytesToIntEx(byte[] src, int offset, int len)
{
    switch (len)
    {
        case 2:
            return ((src[offset++] & 0xFF) | //低位 
                    ((src[offset++] & 0xFF) << 8));
        case 3:
            return ((src[offset++] & 0xFF) | //低位 
                    ((src[offset++] & 0xFF) << 8) |
                    ((src[offset++] & 0xFF) << 16));
        case 4:
            return ((src[offset] & 0xFF) |//低位 
                    ((src[offset++] & 0xFF) << 8) |
                    ((src[offset++] & 0xFF) << 16) |
                    ((src[offset++] & 0xFF) << 24));
        default:
            return 0;
    }
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章