IPv6簡介


IPv6僅僅只是“長”嗎?IPv6的地址長什么樣?平時我們是怎么使用IPv6的呢?編寫網絡程序的時候要怎么處理IPv6?且待本篇一一道來。

為什么需要IPv6?

全球的IP地址由一個名字叫IANA(Internet Assigned Numbers Authority)的機構管理,在它下面有5個分管機構,名字叫分別叫AFRINIC、APNIC、ARIN、PIPE NCC和LACNIC,他們分別負責全球五個不同地區的IP地址分配,中國就歸APNIC管。

IANA只負責將IP地址分配給下面的5個分管機構,分管機構再負責將IP地址分配給相關地區的網絡運營商或者研究機構等。

IPv4的長度只有32位,總共約42億的地址,除去預留的大約6億地址外,實際在公網中可以被使用的地址大約只有36億,而據最新統計,世界人口已經超過了70億,並且截至2016年,人們正在使用的智能手機數量已經超過了20億。

截至2011年01月31日,IANA已經將所有的IP地址分配給了下面的5個分管機構,而到2011年04月15日,APNIC的IP地址已經全部分配完了,就是說,如果我們的中國電信、移動和聯通的IP地址不夠用的話,已經沒有地方可以申請更多的IP地址了。

很明顯,如果每個設備都用一個公網IP的話,IPv4早就不夠用了,雖然現在用NAT的方式還能堅持一段時間,但終究不是長久之策,我們需要一個更大的IP地址空間。

IPv6的優點

更大的地址空間

名字叫IPv6,但它的長度並不是64位,而是128位,總的地址空間大約為3.4*10^38,一個億是10的8次方,那么IPv6就有340萬億億億億個地址(4個億連一起),所以說給地球上的每一粒沙子分配一個IP地址不是在吹牛,是真可以。

可以參考這篇文章這篇文章,里面提到地球上所有沙灘的沙子大約有7.5*10^18粒,這個值跟IPv6的10^38相差了很多個數量級,就算加上沙漠等其它的地方,IPv6的數量也足夠覆蓋它。

點到點通信更方便

IPv6完全有能力為聯網的每個設備分配一個公網IP,於是我們可以不再需要NAT,從而非常方便的實現點到點的直接通信。

說好處之前,先了解一下NAT的缺點:

  • 使用了NAT之后,每次通信都要做一次NAT轉換,影響性能。

  • 處於兩個不同NAT網絡內部的機器不能直接通信,他們之間的通信得依賴第三方的服務器,極大的限制了網絡的連通性,同時所有的數據都會被第三方所監控。

  • 為了支持NAT,很多網絡協議變得很復雜,大大增加了網絡的復雜性。

沒有了NAT之后,當然上面的這些缺點也就沒有了,同時會帶來下面這些比較直觀的好處:

  • 更方便: 想象一下,每個電腦都有公網IP,你電腦出了點問題,找我幫忙看一下,只要把你的IP給我,我就可以連上去了,而我們現在的情況是,兩個人都是內網IP,沒法直接訪問,非得用QQ共享桌面之類的軟件。

  • 更安全: 配合點到點的加密,讓網絡更安全,不給第三方監聽的機會; 以網絡聊天為例,通過使用點到點的聊天軟件,就不用擔心被人監聽聊天記錄了;同時訪問家里的攝像頭不再需要經過第三方服務器,不用擔心給別人看直播了。

IP配置更方便

IPv6有一個功能叫Stateless Auto Configuration,簡單點說,就是可以不借助DHCP服務器實現IP地址的分配,插上網線就能上網。

系統起來后,就會為每個網卡生成一個Link-Local的IP地址,簡單點說就是一個固定的前綴加上mac地址,由於mac地址全球唯一,所以這樣構成的IP地址是唯一的,有了這個地址后,就可以局域網進行通信了,但是這種地址路由器是不會轉發的。

如果網絡里有路由器; 系統會通過廣播的方式問路由器,路由器會返回一個子網前綴,類似於IPv4里面的192.168.0.0/16,系統將子網前綴和mac地址組合起來,構成了一個唯一的IP地址,這個IP地址可以通過路由器路由。

也就是說,就算不做任何配置,系統啟動起來后,網卡就一定會有IPv6地址,有了IPv6地址就可以通信。

當然IP地址也可以由DHCP6服務器來分配,這種方式分配叫做Stateful Auto Configuration。

局域網內更安全

Neighbor Discovery代替了IPv4里面的ARP協議,沒有ARP后,跟ARP相關的攻擊就不存在了

路由更快

  • 跟IPv4不同,IPv6包頭的字段長度是固定的,沒有可選字段,所以路由器不需要檢查IP包頭是否包含可選字段。

  • IPv6包頭里面沒有checksum字段,不需要像IPv4那樣每次TTL減1后都需要重新計算包頭的checksum。

  • IPv6不支持在中途被分片和重組,即不能在路由器和防火牆上被分片,從而減輕了路由器的負擔。

IPv6包頭里面沒有checksum,那么會不會不安全呢?如果數據傳輸的過程中損壞了怎么辦呢?首先,現在的網絡都比較好,出現損壞的情況很少;其次,就算損壞了,有兩種情況,一種是被路由器丟棄或者發到了錯誤的主機,這種情況不會造成什么問題,因為IP層本來就不保證可靠的傳輸,而是由上面的傳輸層來保證(如TCP),另一種情況是接受方收到了數據包,但由於數據包受損,內容已經和發送方發出來的不一樣了,這種情況也是交給上面的傳輸層協議處理,比如UDP、TCP,它們都有自己的校驗碼,完全有能力發現數據損壞的問題。

不允許路由器對IPv6包進行分片,那么怎么保證發送端不會發送太大的數據包呢?首先,IPv6要求入網鏈路至少能傳輸1280字節的IP包,如果出現不能傳輸1280字節IP包這種情況,需要鏈路層自己處理分片和重組的過程;其次,跟IPv4里面PMTUD(Path MTU Discovery)是可選的不同,在IPv6里面,PMTUD是一個非常重要且必須的功能;所以一般情況下發送小於等於1280字節的IP包肯定能到達目的地,加上現在大部分人都用以太網(MTU為1500,包含以太網的包頭),絕大部分情況下一個包過去就能確定PMTU(Path MTU ),不會影響數據傳輸性能。

更安全

在設計IPv4的時候,根本沒有考慮過安全問題。

而在設計IPv6的時候,安全問題作為一個很重要的方面被考慮進來了,尤其是端到端的安全,IPsec正是在這樣的背景下被設計出來的,有了IPsec后,在IP層就能實現安全傳輸。

雖然IPsec也被引入到了IPv4,但由於IPsec連傳輸層的端口都進行了加密,導致IPsec碰到NAT網絡的時候,會造成很多麻煩,雖然現在已經有了解決辦法,但IPsec在IPv4網絡里面還是受到諸多限制。

更好的QoS

IPv6的包頭里面包含了一個叫做Flow Label的字段,專門為QoS服務。

更好的支持移動設備

移動網絡要求設備能在不同的網絡里面快速的切換,並且現有的通信不受切換的影響,在IPv6里面,有專門的協議Mobile IPv6 (MIPv6)來處理這個事情。

IPv6格式

這里不介紹報文的格式,只介紹IPv6地址的格式。

地址表示方式

IPv6地址的128位分成了由冒號分割的8段,每段2個字節16位,這16位由16進制表示,這里是一些例子,左邊是完整的格式,右邊是縮寫格式:

完整的格式 縮寫格式
0000:0000:0000:0000:0000:0000:0000:0000 ::
0000:0000:0000:0000:0000:0000:0000:0001 ::1
FF02:0000:0000:0000:0000:0000:0000:0001 FF02::1
FC00:0001:A000:0B00:0000:0527:0127:00AB FC00:1:A000:B00::527:127:AB
2001:0000:1111:000A:00B0:0000:9000:0200 2001:0:1111:A:B0::9000:200
2001:0DB8:0000:0000:ABCD:0000:0000:1234 2002:DB8::ABCD:0:0:1234 或者 2001:DB8:0:0:ABCD::1234
2001:0DB8:AAAA:0001:0000:0000:0000:0100 2001:DB8:AAAA:1::100

兩條縮寫規則:

  • 用冒號分割的每段里面的前面的0可以省略掉,如:0001:可以縮寫成:1:,:0000:可以縮寫成:0:

  • 如果冒號里面的是0的話,可以忽略掉(相鄰的多個0可以一起忽略掉),直接寫成兩個冒號,如:0000:0000:可以被縮寫成::

注意:如果地址中有多個連續為0的段,只能將其中的一個縮寫成::,如果兩個都縮寫了,就不知道每個縮寫了多少個0,這也是上面的表格中2001:0DB8:0000:0000:ABCD:0000:0000:1234被縮寫成2002:DB8::ABCD:0:0:1234或者2001:DB8:0:0:ABCD::1234的原因,它不能被縮寫成2001:DB8::ABCD::1234,一般的做法是哪種方法省略的0越多就用哪種。

網段表示方式

IPv6和IPv4一樣,也有網段和子網的概念,在IPv6里面,表示子網號或者網段的時候,也是類似的方法,如:2001:0:0:CD30::/60,這個時候前面的地址只需要寫前60位,后面的所有位都用::來縮寫,類似於IPv4里面的192.168.0。0/16,不過要注意的是,這里2001:0:0:CD30::不能把前面的兩個0也縮寫,因為這樣就不是一個合法的IPv6地址了。

IPv6地址類型

IPv6里面有三種地址類型;

  • Unicast: 單播地址,就是我們常用的地址,唯一標識一個網絡接口

  • Anycast: 任意播(直譯有點怪),一類特殊的IP地址,多個網絡接口(不同的設備)都配上相同的地址,往這個地址發送數據的時候,路由器會只發往其中的一個接口,一般發往最近的那一個。(這個好像對實現負載均衡比較有用)

  • Multicast: 多播地址,代表一類unicast的集合,但往這個地址發送數據的時候,會將數據發給屬於這個多播組的每個unicast地址。

IPv6里面沒有類似於IPv4那樣單獨的廣播概念,它的功能被包含在多播里面。

本人對anycast和multicast不是特別了解,所以沒法描述的很清楚。

IPv6地址分類

現有的IP地址被分配成如下幾大類:

類型 前綴 IPv6表示方法
Unspecified 00...00 (128位) ::/128
Loopback 00...01 (128位) ::1/128
Multicast 11111111 FF00::/8
Link-Local unicast 1111111010 FE80::/10
Unique local address 1111110 FC00::/7
Global Unicast 所有其它
  • 全0的地址::/128為未定義地址,大家不要去使用

  • 除了最后一位是1,其它都是0的地址::1/128為本地環回地址,同IPv4里面的127.0.0.1

  • FF00::/8這個網段的地址都是多播地址

  • FE80::/10為Link-Local的單播地址,這類地址不能穿過路由器

  • FC00::/7為本地的單播地址,可以穿過本地的路由器,但不能穿過外網的路由器,即只可以在本地使用,和IPv4里面的192.168.0.0/16相似

  • 全局的單播地址目前只有2000::/3開頭的可以被申請使用,其它的都被預留了

預定義的多播地址

這里是兩個常用的預定義的多播地址:

地址 含義
FF02:0:0:0:0:0:0:1 子網內的所有機器
FF02:0:0:0:0:0:0:2 子網內的所有路由器

后面有例子演示如何使用多播

子網的划分

IPv6要求所有的單播(unicast)地址的子網必須是64位的,即下面這種格式:

 | 64 bits | 64 bits | +-------------------------+-------------------------+ | subnet ID | interface ID | 

如果子網的長度不是64位的話,會導致一些IPv6的功能不可用,詳情請參考IPv6 Unicast Address Assignment Considerations

Interface ID為Modified EUI-64格式,標准里面提供了如何將48位mac地址轉換成EUI-64格式的方法。

IPv6標准要求單播地址的子網必須是64位的,主要是為了簡化IPv6的管理,同時路由也方便,畢竟現在CPU都是64位的,如果子網號超過64位的話,會給路由造成一定的困難,同時64位的接口ID也比較容易存放一個UUID,比如可以容納48位的mac地址,為Stateless Auto Configuration的地址分配提供了足夠的空間。

64位的子網夠用嗎?64位的子網已經可以容納2^64的設備了,相當於40億個現在的IPv4地址空間的規模,實在是想不出還有哪種場合需要更大的子網。

64位的子網浪費嗎?想想IPv4時代,幾個人或者一群人通過NAT共享1個公網IP,而到了IPv6時代,這些人竟然可以擁有2^64個IP地址,想用幾個用幾個,為幾個人分配一個64位的子網是不是有點浪費呢?其實談不上浪費,IPv6的地址就是有那么多,大家都空着不用也是浪費,按道理64位的IP地址在可預見的將來已經夠用了,而之所以采用128位IP加64位子網的方式,是因為能給我們的管理和使用方面帶來很多的方便,如上面提到的便於路由和地址分配等。就算以后IP不夠用了,再來放開子網位數的限制應該問題也不大。

想起了一句話: 等我有了錢,要裝兩條寬帶,一條玩游戲,一條聊QQ。

Linux上配置IPv6

下面的所有例子都在ubuntu-server-x86_64 16.04下執行通過

現在的大部分Linux發行版默認情況下都啟用了IPv6,如果沒有,請參考發行版相關文檔進行配置

#這里有輸出,表示IPv6已結啟用了 dev@ubuntu:~$ test -f /proc/net/if_inet6 && echo "IPv6 is already enabled" IPv6 is already enabled

IPv6啟用后,每個網卡都會有一個IPv6地址,如下:

dev@ubuntu:~$ ifconfig enp0s3 Link encap:Ethernet HWaddr 08:00:27:03:d0:e7 inet addr:192.168.3.12 Bcast:192.168.3.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe03:d0e7/64 Scope:Link ...... lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host ......

這里lo的IPv6地址是環回地址::1,而enp0s3有一個“Scope:Link”的IPv6地址fe80::a00:27ff:fe03:d0e7,這個IP地址即上面說到的Link-local地址,它沒法通過路由器,只能在子網內部使用。

由於IPv6對交換機沒有要求,所以就算沒有支持IPv6的路由器,我們也可以在本地局域網內試玩一下IPv6

通過ip命令就可以給網卡添加IPv6地址,和一個網卡只能有一個IPv4地址不同,一個網卡可以配置多個IPv6地址。

#添加一個global的地址 dev@ubuntu:~$ sudo ip -6 addr add 2001::1/64 dev enp0s3 #添加一個Unique local address地址 dev@ubuntu:~$ sudo ip -6 addr add fd00::1/64 dev enp0s3 dev@ubuntu:~$ ifconfig enp0s3 enp0s3 Link encap:Ethernet HWaddr 08:00:27:03:d0:e7 inet addr:192.168.3.12 Bcast:192.168.3.255 Mask:255.255.255.0 inet6 addr: fd00::1/64 Scope:Global inet6 addr: 2001::1/64 Scope:Global inet6 addr: fe80::a00:27ff:fe03:d0e7/64 Scope:Link ......

再來看看系統默認的路由表:

dev@ubuntu:~$ route -A inet6 Kernel IPv6 routing table Destination Next Hop Flag Met Ref Use If 2001::/64 :: U 256 0 0 enp0s3 fd00::/64 :: U 256 0 0 enp0s3 fe80::/64 :: U 256 1 3 enp0s3 ::/0 :: !n -1 1 832 lo ::1/128 :: Un 0 3 36 lo 2001::1/128 :: Un 0 3 9 lo fd00::1/128 :: Un 0 2 5 lo fe80::a00:27ff:fe03:d0e7/128 :: Un 0 3 193 lo ff00::/8 :: U 256 2 84 enp0s3 ::/0 :: !n -1 1 832 lo

從“Next Hop”列可以看出,這里的所有網段都是本地接口可以直接到達的網段,不需要路由器轉發。

使用IPv6

上節配置好了IPv6之后,我們這節來看看怎么使用這些地址

這里只用一台機器來演示怎么和自己通信,大家有條件的話可以試試兩台機器之間通信,效果是一樣的。

ping6

和IPv4里面的ping相對於的命令是ping6,對於不同類型的地址,ping的方式不一樣(為了節省篇幅,示例中省略了ping成功時的輸出):

#ping lo的環回地址 dev@ubuntu:~$ ping6 ::1 #ping類型為“Scope:Global”的地址 dev@ubuntu:~$ ping6 fd00::1 dev@ubuntu:~$ ping6 2001::1 #ping類型為“Scope:Link”的地址 dev@ubuntu:~$ ping6 -I enp0s3 fe80::a00:27ff:fe03:d0e7 #ping一個多播(Multicast)地址,ff02::1代表子網中的所有機器 dev@ubuntu:~$ ping6 -I enp0s3 ff02::1 PING ff02::1(ff02::1) from fe80::a00:27ff:fe03:d0e7 enp0s3: 56 data bytes 64 bytes from fe80::a00:27ff:fe03:d0e7: icmp_seq=1 ttl=64 time=0.036 ms 64 bytes from fe80::3aea:a7ff:fe6c:ecff: icmp_seq=1 ttl=64 time=0.744 ms (DUP!) 64 bytes from fe80::188d:cbae:80d5:7a7a: icmp_seq=1 ttl=64 time=0.791 ms (DUP!) ...... #可以看到局域網中的其它機器回復的結果,這些IP都是其它機器的“Scope:Link”地址 #這里(DUP!)是由於ping多播地址時會收到多個回復,導致ping認為有重復的應答,其實是正常情況 #選擇其中的任意一個,單獨ping一下試試 dev@ubuntu:~$ ping6 -I enp0s3 fe80::188d:cbae:80d5:7a7a #訪問Link-local的地址的時候,除了-I參數外,我們可以直接這樣訪問 dev@ubuntu:~$ ping6 fe80::188d:cbae:80d5:7a7a%enp0s3 #或者根據enp0s3的id來訪問 #獲取enp0s3的id dev@ubuntu:~$ grep enp0s3 /proc/net/if_inet6 | cut -d' ' -f2 | uniq 02 dev@ubuntu:~$ ping6 fe80::188d:cbae:80d5:7a7a%2

從上面可以看出,ping環回地址和global地址時,直接ping就可以了,而ping多播和Link-Local地址時,需要指定從哪個接口出去,這是因為機器上所有接口的Link-Local地址都屬於同一個網段,當有多個接口時,根本沒辦法自動的判斷應該從哪個接口出去。(不過從上面的路由表里面可以看出,在本地只有一個接口時,已經標識fe80::/64和ff00::/8可以從enp0s3口出去,不確定為什么在這種情況下,應用層的程序還要求指定接口名稱,可能是為了保持統一吧,不管有幾個接口,都一樣的用法)。

注意: 如果是訪問其它機器的link-local地址,-I參數和百分號的后面一定要指定本機出去的接口名稱,而不是目的IP對應的接口名稱

DNS

DNS里面有一個專門的IPv6類型,叫AAAA,查詢的時候指定類型就可以了

#host命令默認情況下只查詢A類地址,即IPv4地址 #指定-t AAAA即可查詢域名的IPv6地址 #這里的結果顯示,baidu.com還不支持IPv6,google.com已經支持了 dev@ubuntu:~$ host -t AAAA baidu.com baidu.com has no AAAA record dev@ubuntu:~$ host -t AAAA google.com google.com has IPv6 address 2607:f8b0:400e:c04::65 #dig命令也是一樣的參數 dev@ubuntu:~$ dig -t AAAA google.com #這里省略輸出結果,有點長

SSH

下面四種方式都可以登陸當前機器

dev@ubuntu:~$ ssh ::1 dev@ubuntu:~$ ssh 2001::1 dev@ubuntu:~$ ssh fe80::a00:27ff:fe03:d0e7%enp0s3 dev@ubuntu:~$ ssh fe80::a00:27ff:fe03:d0e7%2

http

下面以curl來進行演示,如果有圖形界面的瀏覽器的話,可以直接在瀏覽器里面輸入同樣的地址

#--------------------------第一個shell窗口---------------------- #准備一個支持IPv6的http服務器 dev@ubuntu:~$ sudo apt-get install php dev@ubuntu:~$ mkdir web dev@ubuntu:~$ echo "hello world!" > web/index.html #啟動http服務器,監聽所有接口的8080端口 dev@ubuntu:~$ php -S [::]:8080 -t ./web/ PHP 7.0.15-0ubuntu0.16.04.4 Development Server started at Mon Mar 20 23:44:26 2017 Listening on http://[::]:8080 Document root is /home/dev/web Press Ctrl-C to quit. #--------------------------第二個shell窗口---------------------- #確認監聽正確,這里:::8080就表示監聽了所有IPv6和IPv4接口的8080端口 dev@ubuntu:~$ netstat -anp|grep 8080 tcp6 0 0 :::8080 :::* LISTEN 13716/php #先試試用IPv4的地址連過來,沒有問題 dev@ubuntu:~$ curl http://127.0.0.1:8080/ hello world! #IPv6的環回地址 dev@ubuntu:~$ curl http://[::1]:8080/ hello world! #IPv6的global地址 dev@ubuntu:~$ curl http://[2001::1]:8080/ hello world! #link-local地址 dev@ubuntu:~$ curl http://[fe80::a00:27ff:fe03:d0e7%enp0s3]:8080/ hello world! dev@ubuntu:~$ curl http://[fe80::a00:27ff:fe03:d0e7%2]:8080/ hello world!

IPv6編程示例

這里以python代碼為示例,寫了一個UDP的服務器和客戶端,演示如何同時支持IPv4和IPv6。(為了簡化起見,代碼里面沒有做錯誤處理)

server.py

import socket import sys ip,port = sys.argv[1],int(sys.argv[2]) addrinfo = socket.getaddrinfo(ip, port, proto=socket.IPPROTO_UDP)[0] sock = socket.socket(addrinfo[0], socket.SOCK_DGRAM) addr = addrinfo[4] sock.bind(addr) print("Listening on [{}]:{}...".format(addr[0], addr[1])) while True: data, addr = sock.recvfrom(65535) print("Recvfrom [{}]:{}\t{}".format(addr[0], addr[1], data)) sock.sendto(data, addr)

client.py

import socket import sys host,port = sys.argv[1],int(sys.argv[2]) addrinfos = socket.getaddrinfo(host, port, proto=socket.IPPROTO_UDP) for addrinfo in addrinfos: sock = socket.socket(addrinfo[0], socket.SOCK_DGRAM) sock.settimeout(2) data = b'hello' addr = addrinfo[4] sock.sendto(data, addr) print("Sendto [{}]:{}\t{}".format(addr[0], addr[1], data)) try: data, addr = sock.recvfrom(65535) print("Recvfrom [{}]:{}\t{}".format(addr[0], addr[1], data)) except socket.timeout: print("timeout")

如果參數傳入的是域名或者主機名,getaddrinfo函數可能返回多個IP,這時候客戶端需要根據自己的應用特點選擇一個或多個進行通信,在本例中是發送數據包給所有的IP。

getaddrinfo返回的IP列表里面的順序是有講究的,如果對這個很在意的話,請參考rfc6724,默認情況一般是IPv6的地址在前面,在Linux下還可以通過/etc/gai.conf來配置相關的順序。

server使用示例

dev@ubuntu:~/ipv6$ python3 server.py :: 8000 Listening on [::]:8000... dev@ubuntu:~/ipv6$ python3 server.py 0.0.0.0 8000 Listening on [0.0.0.0]:8000... dev@ubuntu:~/ipv6$ python3 server.py 2001::1 8000 Listening on [2001::1]:8000... dev@ubuntu:~/ipv6$ python3 server.py fe80::a00:27ff:fe03:d0e7%enp0s3 8000 Listening on [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000... dev@ubuntu:~/ipv6$ python3 server.py fe80::a00:27ff:fe03:d0e7%2 8000 Listening on [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000...

server綁定所有IPv4和IPv6的接口, 然后client用不同的方式發包

dev@ubuntu:~/ipv6$ python3 server.py :: 8000 Listening on [::]:8000... Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:48033 b'hello' Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:50298 b'hello' Recvfrom [2001::1]:60882 b'hello' Recvfrom [::1]:44664 b'hello' Recvfrom [::ffff:127.0.0.1]:46676 b'hello' Recvfrom [::1]:55518 b'hello' Recvfrom [::ffff:127.0.0.1]:35961 b'hello' Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:36281 b'hello'
dev@ubuntu:~/ipv6$ python3 client.py fe80::a00:27ff:fe03:d0e7%enp0s3 8000 Sendto [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000 b'hello' Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000 b'hello' dev@ubuntu:~/ipv6$ python3 client.py fe80::a00:27ff:fe03:d0e7%2 8000 Sendto [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000 b'hello' Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000 b'hello' dev@ubuntu:~/ipv6$ python3 client.py 2001::1 8000 Sendto [2001::1]:8000 b'hello' Recvfrom [2001::1]:8000 b'hello' dev@ubuntu:~/ipv6$ python3 client.py ::1 8000 Sendto [::1]:8000 b'hello' Recvfrom [::1]:8000 b'hello' dev@ubuntu:~/ipv6$ python3 client.py 127.0.0.1 8000 Sendto [127.0.0.1]:8000 b'hello' Recvfrom [127.0.0.1]:8000 b'hello' #由於localhost在/etc/hosts里面配置了兩個IP,所以這里發了兩個數據包, #並且是先發IPv6的地址 dev@ubuntu:~/ipv6$ python3 client.py localhost 8000 Sendto [::1]:8000 b'hello' Recvfrom [::1]:8000 b'hello' Sendto [127.0.0.1]:8000 b'hello' Recvfrom [127.0.0.1]:8000 b'hello' #通過多播地址發給當前子網中的所有機器 dev@ubuntu:~/ipv6$ python3 client.py FF02:0:0:0:0:0:0:1%enp0s3 8000 Sendto [ff02::1%enp0s3]:8000 b'hello' Recvfrom [fe80::a00:27ff:fe03:d0e7%enp0s3]:8000 b'hello'

參考

Why Allocating a /64 is Not Wasteful and Necessary
Top 10 Features that make IPv6 'greater' than IPv4
IP Version 6 Addressing Architecture

轉自:https://segmentfault.com/a/1190000008794218


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM