IPv6簡介

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

爲何須要IPv6?

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

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

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

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

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

IPv6的優勢

更大的地址空間

名字叫IPv6,但它的長度並非64位,而是128位,總的地址空間大約爲3.4*10^38,一個億是10的8次方,那麼IPv6就有340萬億億億億個地址(4個億連一塊兒),因此說給地球上的每一粒沙子分配一個IP地址不是在吹牛,是真能夠。編程

能夠參考這篇文章這篇文章,裏面提到地球上全部沙灘的沙子大約有7.5*10^18粒,這個值跟IPv6的10^38相差了不少個數量級,就算加上沙漠等其它的地方,IPv6的數量也足夠覆蓋它。ubuntu

點到點通訊更方便

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

相關文章
相關標籤/搜索