<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    網絡通信時字節序轉換原理與網絡字節序、大端和小端模式

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    引言:在進行網絡通信時是否需要進行字節序轉換? 

    相同字節序的平臺在進行網絡通信時可以不進行字節序轉換,但是跨平臺進行網絡數據通信時必須進行字節序轉換。 原因如下:網絡協議規定接收到得第一個字節是高字節,存放到低地址,所以發送時會首先去低地址取數據的高字節。小端模式的多字節數據在存放時,低地址存放的是低字節,而被發送方網絡協議函數發送時會首先去低地址取數據(想要取高字節,真正取得是低字節),接收方網絡協議函數接收時會將接收到的第一個字節存放到低地址(想要接收高字節,真正接收的是低字節),所以最后雙方都正確的收發了數據。而相同平臺進行通信時,如果雙方都進行轉換最后雖然能夠正確收發數據,但是所做的轉換是沒有意義的,造成資源的浪費。而不同平臺進行通信時必須進行轉換,不轉換會造成錯誤的收發數據,字節序轉換函數會根據當前平臺的存儲模式做出相應正確的轉換,如果當前平臺是大端,則直接返回不進行轉換,如果當前平臺是小端,會將接收到得網絡字節序進行轉換。   下面對一些概念做下介紹:

     

    一、大端、小端
    "大端"和"小端"表示多字節值的哪一端存儲在該值的起始地址處;小端存儲在起始地址處,即是小端字節序;大端存儲在起始地址處,即是大端字節序;
    或者說:
    1.小端法(Little-Endian)就是低位字節排放在內存的低地址端(即該值的起始地址),高位字節排放在內存的高地址端;
    2.大端法(Big-Endian)就是高位字節排放在內存的低地址端(即該值的起始地址),低位字節排放在內存的高地址端;
    舉個簡單的例子,對于整型數據0x12345678,它在大端法和小端法的系統中,各自的存放方式如下圖1所示:

    RFID設備管理軟件
    二、網絡字節序
    網絡上傳輸的數據都是字節流,對于一個多字節數值,在進行網絡傳輸的時候,先傳遞哪個字節?也就是說,當接收端收到第一個字節的時候,它將這個字節作為高位字節還是低位字節處理,是一個比較有意義的問題;
    UDP/TCP/IP協議規定:把接收到的第一個字節當作高位字節看待,這就要求發送端發送的第一個字節是高位字節;而在發送端發送數據時,發送的第一個字節是該數值在內存中的起始地址處對應的那個字節,也就是說,該數值在內存中的起始地址處對應的那個字節就是要發送的第一個高位字節(即:高位字節存放在低地址處);由此可見,多字節數值在發送之前,在內存中因該是以大端法存放的;
    所以說,網絡字節序是大端字節序;
    比如,我們經過網絡發送整型數值0x12345678時,在80X86平臺中,它是以小端發存放的,在發送之前需要使用系統提供的字節序轉換函數htonl()將其轉換成大端法存放的數值;如下圖2所示:
    RFID設備管理軟件
    三、字節序測試
    不同CPU平臺上字節序通常也不一樣,下面這個簡單的代碼可以測試不同平臺上的字節序:
    #include <stdio.h>
    #include <netinet/in.h>
    int main(int argc,char** argv)
    {
      int num = 0x12345678;
      unsigned char* pc = (unsigned char*)(&num);
      printf("local order:\n");
      printf("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
      printf("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
      printf("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
      printf("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
      num = htonl(num);
      printf("htonl order:\n");
      printf("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
      printf("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
      printf("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
      printf("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
      return 0;
    }
    SPARC平臺上的輸出:
    local order:
    [0]: 0x12 addr:4290770212 //高位字節存放在低地址處,則是大端法;
    [1]: 0x34 addr:4290770213
    [2]: 0x56 addr:4290770214
    [3]: 0x78 addr:4290770215 //低位字節存放在高地址處;
    htonl order:
    [0]: 0x12 addr:4290770212 //由此看出,主機字節序與網絡字節一樣;
    [1]: 0x34 addr:4290770213
    [2]: 0x56 addr:4290770214
    [3]: 0x78 addr:4290770215
    X86平臺上的輸出:
    local order:
    [0]: 0x78 addr:4289157020 //低位字節存放在低地址處,則是小端法;
    [1]: 0x56 addr:4289157021
    [2]: 0x34 addr:4289157022
    [3]: 0x12 addr:4289157023 //高位字節存放在高地址處;
    htonl order:
    [0]: 0x12 addr:4289157020 //由此看出,主機字節序與網絡字節不一樣;
    [1]: 0x34 addr:4289157021
    [2]: 0x56 addr:4289157022
    [3]: 0x78 addr:4289157023
    INTEL平臺上的輸出:
    local order:
    [0]: 0x78 addr:1245044    //低位字節存放在低地址處,則是小端法;
    [1]: 0x56 addr:1245045
    [2]: 0x34 addr:1245046
    [3]: 0x12 addr:1245047    //高位字節存放在高地址處;
    htonl order:
    [0]: 0x12 addr:1245044    //由此看出,主機字節序與網絡字節不一樣;
    [1]: 0x34 addr:1245045
    [2]: 0x56 addr:1245046
    [3]: 0x78 addr:1245047
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全