1. 程式人生 > >TCP/IP網路程式設計之地址族與資料序列

TCP/IP網路程式設計之地址族與資料序列

IP地址分為IPv4與IPv6 前者是4位元組地址族後者是16位元組地址族,兩者的差異主要是表示IP地址所使用的位元組數

IPv4的4位元組地址分為網路地址與主機地址,並且分為A、B、C、D、E四種類型


說明:

A類地址的首位元組範圍是:0-127

B類地址的首位元組範圍是:128-191

C類地址的首位元組範圍是:192-223

或者也可以這樣分

A類地址的首位是以0開頭

B類地址的前兩位是以10開頭

C類地址的前三位是以110開頭

網路地址與主機地址

網路地址是為區分網路而設定的一部分IP地址。

向某個IP地址傳輸資料時,是先根據網路地址找到,把資料傳輸到目標網路再根據主機地址將資料傳遞給目標計算機。其實質過程是向構成目標網路的路由器或者交換機傳輸資料,其後又接收資料的路由器根據資料中的主機地址向目標傳遞資料。

路由器或者交換機:一種完成外網與本網主機之間的資料交換的物理裝置。

埠號

在同一作業系統中用於區分不同套接字,無法將一個埠號分配給相同種類的不同套接字,埠號由16位構成,範圍是0~65535, 但是0~1023是知名埠,用於分配給特定程式,我們應該使用這之外的埠,另外TCP套接字與UDP套接字可以使用同一埠。

linux系統為例:

struct sockaddr_in

{

      sa_family_t      sin_family;   //地址族                          可取值AF_INET IPv4地址族 AF_INET6 IPv6地址族

      uint16_t            sin_port;     //16位TCP/UDP埠號   16位埠號,需要傳遞網路位元組序

      struct in_addr   sin_addr;    //32位IP地址                    32位IP地址資訊,也需要網路位元組序,結構體in_addr宣告為uint32_t,故直接當作32位整數即可

      char                  sin_zero[8];  //不使用                         為使結構體struct sockaddr_in與結構體sockaddr大小一致的填充

};

該結構體中的 in_addr用來存放32位的IP地址,定義如下

struct in_addr

{

    In_addr_t    s_addr;//32位IP地址

};

在使用時直接使用結構體struct sockaddr_in變數再將其強制轉換為sockaddr型別變數即可。

位元組序:

因為主機位元組序分為大端序與小端序,所以在網路傳輸資料時約定同一的方式,網路位元組序,即大端序

大端序:高位低地址

小端序:高位高地址

如:儲存int型別資料0x12345678       最左邊為高位,最右邊為低位

大端序: 0x12     0x34      0x 56     0x78

高位--------------------------------------------------低位

低地址---------------------------------------------高地址

可見:大端序中最先儲存最高位

小端序:0x78      0x56      0x34      0x12

低位--------------------------------------------------高位

低地址---------------------------------------------高地址

可見:小端序中最先儲存最低位

Intel系列cpu以小端序儲存資料、51系列微控制器以大端序儲存資料

實際在傳輸資料時的自動過程:將資料轉換成網路位元組序傳輸,將網路位元組序的資料轉化為主機序接收

由於儲存IP地址與埠號的變數需要網路位元組序,這需要通過函式:

unsigned short htons (unsigned short);             //h主機位元組序 to  n網路位元組序  s 兩位元組short,用於埠的轉換整個函式的意思將埠號從主機位元組序轉化為網路位元組序

unsigned  short ntohs(unsigned  short);

unsigned  long htons (unsignedlong);

unsigned  long ntohs (unsignedlong);

函式名中:h表示主機位元組序,n表示網路位元組序 s表示short, l表示long  以s結尾的函式用於埠號的轉換,以l結尾的函式用於IP地址的轉換

我們平時使用的IP地址為點分十進位制的字串形式,需要將其轉化為32位的整數資料

下面兩個函式可以幫我們解決這個問題,他們得到32位整數已經是網路位元組序了,無需再次轉換

in_addr_t inet_addr(const char* string);

int inet_aton(const char *string,struct in_addr *addr);  改函式的第二個引數直接傳遞結構體struct sockaddr_in變數的成員sin_addr的地址即可,函式將得到的網路位元組序的IP地址直接存入結構體變數中

函式char *inet_ntoa(struct in_addr adr);可將傳入的整數型IP地址轉換為字串格式並返回,如果需要儲存返回的點分十進位制的字串形式ip應該將返回的字串拷貝(strcpy函式)到自定義的空間中,因為一旦再次呼叫,原來返回的字串將被覆蓋

網路地址的初始化

定義結構體sockaddr_in 變數,然後將變數清零(memset、或bzero)  接著向結構體變數指定地址族、賦值網路位元組序的ip、網路位元組序埠號

注意:點分十進位制的IP與埠號是字串形式,  ip地址.通過上面講的兩個函式轉換為網路位元組序的整數後賦值給結構體變數的成員,埠號通過函式atoi轉換為整數後再通過函式htons轉化為網路位元組序後賦值給結構體變數成員

另外,當是為伺服器設定ip地址時,可直接使用常數INADDR_ANY自動獲取執行伺服器端計算機IP地址,表示監聽指定埠的所有網絡卡/IP收到的資料

回送地址:127.0.0.1 一般用於網路軟體測試以及本地機程序間通訊