天天看點

Linux網絡程式設計基礎---IPV4位址

v IPV4位址

我們使用的網絡目前都是 IPv4 (IP version 4) 版本的,是以使用到的 IP 位址也是第 4 版本的,IPv6 版本的也有 ,不過先學好基礎的嘛。是以,這個部落格涉及到的所有的網絡程式設計,都是基于 IPv4 的東東。在學習 IPv4 前,掌握 ip 位址相關的知識那是必須的必。

1. IP 位址

1.1 in_addr_t 還是 in_addr?

IPv4 位址,本質上是 32 位無符号整數。在 Linux 作業系統中,使用了 in_addr_t 類型來表示這樣一個 4 位元組的整數,它是由 typedef 定義的。

typedef uint32_t in_addr_t;

in_addr_t 這個類型儲存的資料,到底是按本機位元組序儲存的,還是網絡位元組序儲存的,這是不确定的!!!

為了解決此問題,Linux 又定義了一個新的結構體類型 struct in_addr,它明确的表示,它儲存的 ip 位址就是網絡位元組序的!!!

struct in_addr {

  in_addr_t s_addr;

}

如果說你傳了一個本機位元組序的 unsigned int 類型的整數給 in_addr 的 s_addr 成員,很抱歉,後面使用到該結構體的函數都會出錯。

2. ip 位址表示方法

在第 1 節中也說了,ip 位址實際上就是一個 unsigned int 類型的整數。比方說接下來你和你同學說,你把你的 ip 位址配置成 0xc0a8a605 吧……你同學可能覺得你是從火星來的。。。

是以說,生活中使用整數來表示 ip 位址是相當不友善的,我們平時實際上都是用“點分十進制(dotted-decimal)”這種表示方法,比如 192.168.1.1 等等類似這樣的。

點分十進制表示的 ip 位址和整數表示法之間的轉換相當容易,就比如說 0xc0a8a605,先将其拆分成 4 個位元組:c0.a8.a6.05,然後将 4 個部分的 16 進制數變成 10 進制,即 192.168.166.5,是不是很容易?

3. 制作in_addr類型的位址

比方我們需要把 192.168.166.5 儲存成 in_addr 類型的位址,編寫下面的代碼就行了:

struct in_addr addr;

addr.s_addr = htonl(0xc0a8a605);

這樣做看起來有點麻煩!每次都要自己先把點分十進制轉成整數,然後再把整數轉成網絡位元組序!

還好,Linux 提供一些函數,能夠相當友善的幫我們把點分十進制的 ip 位址轉換成 in_addr 類型。

4. 和IP位址轉換相關的函數

下面這些函數中,aton 中的 a(address) 表示點分十進制的位址,n 表示網絡位元組序位址,ntoa 類似。

函數 lnaof 表示 local network address part of the Internet address in,即主機号。

函數 netof 表示 network number part of the Internet address in,即網絡号。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 将點分十進制直接轉換成 in_addr 類型,我們很喜歡這個函數
int inet_aton(const char *cp, struct in_addr *inp);

// 将點分十進制轉換成 in_addr_t 類型,傳回值儲存的是網絡位元組序
in_addr_t inet_addr(const char *cp);

// 将點分十進制轉換成 in_addr_t 類型,傳回值儲存的是本機位元組序
in_addr_t inet_network(const char *cp);

// 将 in_addr 位址轉換成點分十進制,注意這個函數不是線程安全的
char *inet_ntoa(struct in_addr in);

// 根據網絡号和主機号制作 in_addr 類型位址
struct in_addr inet_makeaddr(int net, int host);

// 傳回 ip 位址的主機号,傳回的結果是本機位元組序的
in_addr_t inet_lnaof(struct in_addr in);

// 傳回 ip 位址的網絡号,傳回的結果是本機位元組序的
in_addr_t inet_netof(struct in_addr in);
           

Ps:IP位址轉換的函數還是挺多的,要好好的把這些程式都做一遍實驗,好好敲一遍!

5 将點分十進制轉換成網絡位元組序的兩個函數的差別

将點分十進制轉換為網絡位元組序的函數有inet_addr 和 inet_aton。

但是,這兩個函數是有差別的,inet_addr 函數如果出錯會傳回 -1,即 0xffffffff,因些位址 255.255.255.255 是無法轉換的,雖然将此位址轉換成的結果也是 0xffffffff,但是錯誤的 ip 位址比如 300.200.200.200 轉換的結果也是 0xffffffff,是以 inet_addr 在不十分嚴謹的情況下才會使用。

inet_aton 是比較正式的,它單獨使用傳回值判斷轉換的位址是否有效,如果傳回為 0,表示轉換的位址是錯誤的。

6. 知識點總結

v in_addr_t 和 in_addr 的差別和聯系

v in_addr 是網絡位元組序的

v in_addr_t 是什麼位元組序是不确定的

v 掌握相關的轉換函數

v inet_addr 和 inet_aton 的差別

繼續閱讀