c 對ipv4和ipv6位址的相容處理

2021-10-09 09:48:20 字數 1985 閱讀 5497

目前ipv6的應用越來越廣泛,慢慢將變成強制的標準,做網路應用開發的,在未來會越來越的要開始支援ipv6,但是ipv6肯定不是一下子就可以大範圍應用的,必然有一段時間ipv4與ipv6共存,要做到對ipv4和ipv6的同時支援。

關於如何讓程式支援ipv6 可以參考  

示例**見: 

這個文章只講如何相容ipv4和ipv6

如果使用asio這樣成熟的網路庫,就無需再看此文,asio已經將底層的差別遮蔽。

這裡只討論從socket層面自已開發網路庫時,支援ipv4 和ipv6會遇到的情況。

使用這樣的結構體既可以表示ipv4的位址,又可以表示ipv6位址

struct myaddrinfo;

};

union聯合體中的三個結構體 大概如下所示(與標準有一些區別,主要方便理解): 源自

/* structure describing a generic socket address.  */

struct sockaddr

;/* structure describing an internet socket address. */

struct sockaddr_in

;/* ditto, for ipv6. */

struct sockaddr_in6

;

此處由於windows平台下和linux平台下對sockaddr_in6的定義有些區別,所以需要盡量使用兩個平台下定義相同的變數,避免使用系統中定義名稱的變數。

獲取ip位址

//返回ipv4 位址

static uint32_t get_ipv4(const myaddrinfo &addr)

//返回ipv6 位址

static in6_addr get_ipv6(const myaddrinfo &addr)

ip位址字串

//返回ipv4或v6位址字串

static inline std::string get_ipstr(const myaddrinfo &addr)

else if (addr.ai_family == af_inet6)

else return std::string("");

}

獲取埠號

static inline uint16_t get_port(const myaddrinfo &addr)

else if (addr.ai_family == af_inet6)

else return 0;

}

如果程式監聽的是  ::0  位址,即ipv6位址, 對於同時具有ipv4位址和 ipv6位址的 雙棧伺服器來講, 會同時監聽ipv4和ipv6協議棧上的某個埠,客戶端連線伺服器的時候,如果使用的是ipv4連線的,顯示出的結果是 ::ff:192.168.3.8這樣經過對映的ipv6的位址。

如果要判斷是否是ipv4對映的位址,可以用如下辦法

//是否是v4對映的v6位址

; static const prefix prefix;

static const int prefix_size = 12;

// [00:00:00:00:00 :00:00:00:00:00 :ff:ff] 共12個位元組

if (memcmp(&prefix, &(addr.addr6.sin6_addr), prefix_size) == 0)

return true;

else

return false;

} //ipv4位址,對映前的位址 (網路位元組序)

static uint32_t get_ipv4_inv6(const myaddrinfo &addr)

更詳細的例子可以參考:

參考:

nginx 的實現 

校驗IPv4和IPv6位址和URL位址

function validateip obj obj val dialogtop alert alert warning return false 呼叫 onblur validateip this function addfilterip images delete.png onclick de...

IPv4與IPv6位址格式詳解

ipv4位址是類似 a.b.c.d 的格式,它是32位,用 分成四段,用10進製表示 ipv6位址類似 x x x x x x x x的格式,它是128位的,用 分成8段,每個x是乙個16進製制數 16 2 4 可見,ipv6位址空間相對於ipv4位址有了極大的擴充 ipv6 位址的長度為 128 ...

IPv6知識概述 IPv6位址

首選格式 x x x x x x x x x表示乙個4位十六進製制數 典型的例子如下所示 2000 0000 0000 0000 0001 2345 6789 abcd ipv6位址每段中的前導0是可以去掉的,但是至少要保證每一段有乙個數字。將不必要的前導0去掉後,上述位址可以表示為 2000 0 ...