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
