網路位元組序和主機位元組序詳解!!!
我們都知道,如今的通訊方式已經趨向與多樣化,異構通訊(計算機軟體(作業系統) + 計算機硬體(核心架構,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);
引數是一個結構體,所以要呼叫必須先定義一個結構體。