網路位元組序列,本機位元組序列

來源:互聯網
上載者:User

//位元組序列問題
目標機器:
    小端序列(little-endian):低地址中存放的是字資料的低位元組,高地址存放的是字資料的高位元組
        常用的x86,x64都是這種類型的
        
    //同網路位元組序列
    大端序列(big-endian):字資料的高位元組儲存在低地址中,而字資料的低位元組則存放在高地址中
        Sun公司的機器Sparc架構
                                                                             高<-----低
    16bit寬的數0x1234,程式中此種情況為:   0x1234
        地址:0x4000    0x4001
        大端:0x12        0x34
        小端:0x34        0x12
        
    32bit寬的數0x12345678在Little-endian模式CPU記憶體中的存放方式(假設從地址0x4000開始存放)為:
        記憶體位址    0x4000     0x4001    0x4002    0x4003
        存放內容      0x78          0x56         0x34        0x12

    而在Big-endian模式CPU記憶體中的存放方式則為:
        記憶體位址    0x4000    0x4001    0x4002    0x4003
        存放內容      0x12        0x34          0x56        0x78

    雖然記憶體中儲存方法不同,但是程式中的寫法和表示方法一致,當涉及到二進位的處理的時候需要位元組序列轉換。
    
    //檢查CPU類型
    int checkCPU()
    {
       union w{  
        int  a;
        char b;
       }c;
       c.a = 1;

       return(c.b ==1);    //True 則從低到高儲存,小端
    }

    網路位元組序定義:
        收到的第一個位元組被當作高位看待,這就要求發送端發送的第一個位元組應當是高位。
        而在發送端發送資料時,發送的第一個位元組是該數字在記憶體中起始地址對應的位元組。
        可見多位元組數值在發送前,在記憶體中數值應該以大端法存放。
        網路位元組序說是大端位元組序。

//位元組序測試程式
//不同cpu平台上位元組序通常也不一樣,下面寫個簡單的C程式,它可以測試不同平台上的位元組序。
#include <stdio.h>
#include <netinet/in.h>
int main()
{
    int i_num = 0x12345678;
    printf("[0]:0x%x\n", *((char *)&i_num + 0));
    printf("[1]:0x%x\n", *((char *)&i_num + 1));
    printf("[2]:0x%x\n", *((char *)&i_num + 2));
    printf("[3]:0x%x\n", *((char *)&i_num + 3));
 
    i_num = htonl(i_num);
    printf("[0]:0x%x\n", *((char *)&i_num + 0));
    printf("[1]:0x%x\n", *((char *)&i_num + 1));
    printf("[2]:0x%x\n", *((char *)&i_num + 2));
    printf("[3]:0x%x\n", *((char *)&i_num + 3));
 
    return 0;
}

//在80X86CPU平台上,執行該程式得到如下結果:
[0]:0x78
[1]:0x56
[2]:0x34
[3]:0x12

[0]:0x12
[1]:0x34
[2]:0x56
[3]:0x78

//通過對大小端的儲存原理分析可發現,對於 char 型資料,由於其只佔一個位元組,所以不存在這個問題,
//這也是一般情況下把資料緩衝區定義成 char 類型 的原因之一。對於 IP 位址、連接埠號碼等非 char 型資料,
//必須在資料發送到網路上之前將其轉換成大端模式,在接收到資料之後再將其轉換成符合接收端主機的儲存模式。

//Linux 系統為大小端模式的轉換提供了 4 個函數,輸入 man byteorder 命令可得函數原型:
#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

//轉換函式演算法
DWORD ToLittleEndian(DWORD dwBigEndian)
{
    BYTE* p = (BYTE*)&dwBigEndian;
    return (DWORD)(p[0] << 24) + (DWORD)(p[1] << 16) +
        (DWORD)(p[2] << 8) + (DWORD)p[3];
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.