<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>
  • 網站首頁 > 物聯資訊 > 技術分享

    ntohs, ntohl, htons,htonl的比較和詳解

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

    在C/C++寫網絡程序的時候,往往會遇到字節的網絡順序和主機順序的問題。

    這時就可能用到htons(), ntohl(), ntohs(),htons()這4個網絡字節順序與本地字節順序之間的轉換函數:
          htonl()--"Host to Network Long int"     32Bytes
          ntohl()--"Network to Host Long int"     32Bytes
          htons()--"Host to Network Short int"   16Bytes
          ntohs()--"Network to Host Short int"   16Bytes

    之所以需要這些函數是因為計算機數據表示存在兩種字節順序:NBO與HBO。

     

     

    網絡字節順序NBO(Network Byte Order):
          按從高到低的順序存儲,在網絡上使用統一的網絡字節順序,可以避免兼容性問題。

    主機字節順序(HBO,Host Byte Order):
          不同的機器HBO不相同,與CPU設計有關,數據的順序是由cpu決定的,而與操作系統無關。 
          如 Intel   x86結構下,short型數0x1234表示為34 12, int型數0x12345678表示為78 56 34 12 。
          如IBM   power PC結構下,short型數0x1234表示為12   34, int型數0x12345678表示為12 34 56 78。   

     由于這個原因不同體系結構的機器之間無法通信,所以要轉換成一種約定的數序,也就是網絡字節順序,其實就是如同power   pc那樣的順序 。在PC開發中有ntohl和htonl函數可以用來進行網絡字節和主機字節的轉換。

     

    在Linux系統下:htonl(),htons(), ntohl(), ntohs()的頭文件及函數定義:
      #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);     在windows系統下htonl(),htons(), ntohl(), ntohs(), inet_addr()使用說明

    ntohs()  

      簡述:
      將一個無符號短整形數從網絡字節順序轉換為主機字節順序。
      #include <winsock.h>
      u_short PASCAL FAR ntohs( u_short netshort);
      netshort:一個以網絡字節順序表達的16位數。
      注釋:
      本函數將一個16位數由網絡字節順序轉換為主機字節順序。
      返回值:ntohs()返回一個以主機字節順序表達的數。

    ntohl() 

           簡述:
      將一個無符號長整形數從網絡字節順序轉換為主機字節順序。
      #include <winsock.h>
      u_long PASCAL FAR ntohl( u_long netlong);
      netlong:一個以網絡字節順序表達的32位數。
      注釋:
      本函數將一個32位數由網絡字節順序轉換為主機字節順序。
      返回值:
      ntohl()返回一個以主機字節順序表達的數。

    htons()
           簡述:
      將主機的無符號短整形數轉換成網絡字節順序。//將無符號短整型主機字節序轉換為網絡字節序
      #include <winsock.h>
      u_short PASCAL FAR htons( u_short hostshort);
      hostshort:主機字節順序表達的16位數。
      注釋:
      本函數將一個16位數從主機字節順序轉換成網絡字節順序。
      返回值:
      htons()返回一個網絡字節順序的值。
      簡單地說,htons()就是將一個數的高低位互換
      (如:12 34 --> 34 12)
      VB表示:
      MsgBox Hex(htons(&H1234))
      顯示值為 3412

    htonl()
          簡述:
      將主機的無符號長整形數轉換成網絡字節順序。//將無符號長整型網絡字節序轉換為主機字節序
      #include <winsock.h>
      u_long PASCAL FAR htonl( u_long hostlong);
      hostlong:主機字節順序表達的32位數。
      注釋:
      本函數將一個32位數從主機字節順序轉換成網絡字節順序。
      返回值:
      htonl()返回一個網絡字節順序的值。

    inet_addr()

           簡述:
           將一個點間隔地址轉換成一個in_addr。
      #include <winsock.h>
      unsigned long PASCAL FAR inet_addr( const struct FAR* cp);
      cp:一個以Internet標準“.”間隔的字符串。例如202.38.214.xx
           當IP地址為255.255.255.255是被認為無效IP地址。
           本函數解釋cp參數中的字符串,這個字符串用Internet的“.”間隔格式表示一個數字的Internet地址。
        返回值:
        一個無符號長整形數,可用作Internet地址。所有Internet地址以網絡字節順序返回(字節從左到右排列)。

    inet_ntoa()
        簡述:
      將網絡地址轉換成“.”點隔的字符串格式。
      #include <winsock.h>
      char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
      in:一個表示Internet主機地址的結構。
      注釋:
    本函數將一個用in參數所表示的Internet地址結構轉換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。請注意
    inet_ntoa()返回的字符串存放在WINDOWS套接口實現所分配的內存中。應用程序不應假設該內存是如何分配的。在同一個線程的下一個WINDOWS套接口調用前,數據將保證是有效。
    當IP地址為255.255.255.255是認為有效IP地址。這是與inet_addr()的區別
      返回值:
      若無錯誤發生,inet_ntoa()返回一個字符指針。否則的話,返回NULL。其中的數據應在下一個WINDOWS套接口調用前
    復制出來。

    inet_aton()
        與inet_ntoa()作用相反。

    inet_pton()
        簡述:
        本函數將點分十進制轉換為整數
          #include <sys/types.h>
      #include <sys/socket.h>
      #include <arpa/inet.h>
      int inet_pton(int af, const char *src, void *dst);
      這個函數轉換字符串到網絡地址,第一個參數af是地址族,轉換后存在dst中
        inet_pton 是inet_addr的擴展,支持的多地址族有下列:
      af = AF_INET
      src為指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函數將該地址
      轉換為in_addr的結構體,并復制在*dst中
      af =AF_INET6
      src為指向IPV6的地址,,函數將該地址轉換為in6_addr的結構體,并復制在*dst中
      如果函數出錯將返回一個負值,并將errno設置為EAFNOSUPPORT,如果參數af指定的地址族和src格式不對,函數將返
    回0。
           #include <sys/types.h>
      #include <sys/socket.h>
      #include <arpa/inet.h>
      const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
      這個函數轉換網絡二進制結構到ASCII類型的地址,參數的作用和上面相同,只是多了一個參數socklen_t cnt,他是所

        指向緩存區dst的大小,避免溢出,如果緩存區太小無法存儲地址的值,則返回一個空指針,并將errno置為ENOSPC

    atoi()

    array to integer將字符串轉換為整形數

     

     

    首先,假設你已經有了一個sockaddr_in結構體ina,你有一個IP地址"132.241.5.10" 要儲存在其中,你就要用到函數inet_addr(),將IP地址從 點數格式轉換成無符號長整型。
    使用方法如下:
    ina.sin_addr.s_addr = inet_addr("132.241.5.10");
    注意,inet_addr()返回的地址已經是網絡字節格式,所以你無需再調用 函數htonl()。
    我們現在發現上面的代碼片斷不是十分完整的,因為它沒有錯誤檢查。 顯而易見,當inet_addr()發生錯誤時返回-1。記住這些二進制數字?(無符 號數)-1僅僅和IP地址255.255.255.255相符合!這可是廣播地址!大錯特 錯!記住要先進行錯誤檢查。
    好了,現在你可以將IP地址轉換成長整型了。有沒有其相反的方法呢? 它可以將一個in_addr結構體輸出成點數格式?這樣的話,你就要用到函數 inet_ntoa()("ntoa"的含義是"network to ascii"),就像這樣: 
    printf("%s",inet_ntoa(ina.sin_addr));
    它將輸出IP地址。需要注意的是inet_ntoa()將結構體in-addr作為一 個參數,不是長整形。同樣需要注意的是它返回的是一個指向一個字符的 指針。它是一個由inet_ntoa()控制的靜態的固定的指針,所以每次調用 inet_ntoa(),它就將覆蓋上次調用時所得的IP地址。例如:
    char *a1, *a2;
    a1 = inet_ntoa(ina1.sin_addr); /* 這是198.92.129.1 */
    a2 = inet_ntoa(ina2.sin_addr); /* 這是132.241.5.10 */
    printf("address 1: %s ",a1);
    printf("address 2: %s ",a2);
    輸出如下:
    address 1: 132.241.5.10
    address 2: 132.241.5.10
    假如你需要保存這個IP地址,使用strcopy()函數來指向你自己的字符指針。

    ***********************************************************************************************************************************

    測試代碼如下

    #include 
    #include 
    #include 
    #include 
    #include 
    int main(int argc, char* argv[])
    {
             struct in_addr addr1,addr2;
             ulong   l1,l2;
             l1= inet_addr("192.168.0.74");
             l2 = inet_addr("211.100.21.179");
             memcpy(&addr1, &l1, 4);
             memcpy(&addr2, &l2, 4);

             printf("%s : %s ", inet_ntoa(addr1), inet_ntoa(addr2));    //注意這一句的運行結果

             printf("%s ", inet_ntoa(addr1));
             printf("%s ", inet_ntoa(addr2));
             return 0;
    }
    實際運行結果如下:
    192.168.0.74 : 192.168.0.74       //從這里可以看出,printf里的inet_ntoa只運行了一次。
    192.168.0.74
    211.100.21.179

    inet_ntoa返回一個char *,而這個char *的空間是在inet_ntoa里面靜態分配的,所以inet_ntoa后面的調用會覆蓋上一次的調用。第一句printf的結果只能說明在printf里面的可變參數的求值是從右到左的,僅此而已。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全