1. 程式人生 > >網路位元組序和主機位元組序詳解!!!

網路位元組序和主機位元組序詳解!!!

我們都知道,如今的通訊方式已經趨向與多樣化,異構通訊(計算機軟體(作業系統) +    計算機硬體(核心架構,ARM,x86)不同)也已經很普遍了,如,手機和電腦中的qq進行通訊,,,

同時,在計算機設計之初,對記憶體中資料的處理也有不同的方式,(低位資料儲存在低位地址處或者高位資料儲存在低位地址處),然而,在通訊的過程中(ISO/OSI模型和TCP/IP四層模型中),資料被一步步封裝(然後加入資訊首部),當傳到目的段時,被一步步解封,然後獲取資料

從上面我們可以看出,資料在傳輸的過程中,一定有一個標準化的過程,也就是說:從主機a到主機b進行通訊,

a的固有資料儲存-------標準化--------轉化成b的固有格式

如上而言:a或者b的固有資料儲存格式就是自己的主機位元組序,上面的標準化就是網路位元組序(也就是大端位元組序)

a的主機位元組序----------網路位元組序 ---------b的主機位元組序

主機位元組序:

就是自己的主機內部,記憶體中資料的處理方式,可以分為兩種:

大端位元組序(big-endian):按照記憶體的增長方向,高位資料儲存於低位記憶體中

小端位元組序(little-endian):按照記憶體的增長方向,高位資料儲存於低位記憶體中

但是,如何知道我們的主機是那一種的呢???這個我們可以通過程式來進行驗證:

<span style="font-size:18px;">#include <stdio.h>
#include <arpa/inet.h>

int main(){

                unsigned long a = 0x12345678;
                unsigned char *p = (unsigned char *)(&a);

                printf("主機位元組序:%0x    %0x   %0x   %0x\n",  p[0], p[1], p[2], p[3]);

                unsigned long b = htonl(a);  //將主機位元組序轉化成了網路位元組序
                
                p = (unsigned char *)(&b);

                printf("網路位元組序:%0x    %0x   %0x   %0x\n",  p[0], p[1], p[2], p[3]);
                return 0;
        }  </span>
執行結果:

可以看到我的當前主機是:小端位元組序

關於:htonl

<span style="font-size:18px;">#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);</span>

h是主機host,n是網路net,l是長整形long,s是短整形short,所以上面這些函式還是很好理解的

<span style="font-size:18px;">#include <stdio.h>
#include <arpa/inet.h>

int main()
{
        struct in_addr ipaddr;
        unsigned long addr = inet_addr("192.168.1.100");
        printf("addr = %u\n", ntohl(addr));

        ipaddr.s_addr = addr;
        printf("%s\n", inet_ntoa(ipaddr));      
        return 0;       
} </span>
執行結果:

值得注意的是:

in_addr_in   inet_addr(const char *strptr);

inet_addr的引數是一個:點分十進位制字串,返回的值為一個32位的二進位制網路位元組序的IPv4地址,不然的話就是:INADDR_NONE

而返回值為:in_addr_t:IPv4,一般為uint32_t

所以也可以定義為:unsigned long

char * inet_ntoa(struct in_addr inaddr);

引數是一個結構體,所以要呼叫必須先定義一個結構體。