Java的IPv6相關屬性preferIPv4Stack、preferIPv6Addresses介紹


IPv6背景介紹

  目前被廣泛使用的IPv4,它的最大問題是網絡地址資源有限。IPv4僅有32二進制位,滿打滿算也僅有不到43億個IP地址,已經完全不能滿足目前需求。IPv6有128二進制位,地址數量非常龐大。目前主流操作系統早已支持IPv6,Google、Facebook和Yahoo等網站也早已支持IPv6。目前已有大量國內網站和APP已經支持IPv6。未來數年將是IPv4到IPv6的過渡時期,IPv6和IPv4會並存,IPv6使用率也會逐漸提高。

Java對IPv6的支持

在Networking IPv6 User Guide文檔中,介紹了Java對IPv6的支持情況:

IPv6 in Java is transparent and automatic. Porting is not necessary; there is no need to recompile source files.

Java中對IPv6的支持是透明的且自動化的,無需移植,也無需重新編譯源碼。相對於其他語言而言(例如C++),Java很好封裝了IPv4和IPv6兩種版本的不同,Java一般不需要在編寫代碼時關注IPv6如何支持,一個原本運行在IPv4環境的代碼放到支持IPv6環境中一般也可以直接使用。

Java IPv6相關系統屬性

由於Java封裝了IPv4和IPv6的差異,在代碼層面上不需要關注同時也無法設置使用IPv4還是IPv6,Java提供了java.net.preferIPv4Stackjava.net.preferIPv6Addresses兩個系統屬性,用於設置協議棧和地址族的選擇。

這兩個系統參數既可以在Java代碼中設置:

System.setProperty("java.net.preferIPv4Stack", "true");

也可以在啟動時通過JVM參數設置: 

-Djava.net.preferIPv4Stack=true

java.net.preferIPv4Stack(默認值false) 

官方文檔解釋:

If IPv6 is available on the operating system, the underlying native socket will be an IPv6 socket. This allows Java applications to connect to, and accept connections from, both IPv4 and IPv6 hosts.

java.net.preferIPv4Stack為默認值false時,在支持IPv6的雙棧系統上,使用Java的Socket會默認通過底層native方法創建一個IPv6 Socket,這個IPv6 Socket可以同時支持和IPv4或IPv6主機通信。如果設置為true,Java程序將無法使用IPv6進行網絡通信,也就是僅支持IPv4。

例如,當TCP客戶端java.net.preferIPv4Stack設置為true時,如果想創建一個host為IPv6的Socket,會拋出異常java.net.SocketException: Protocol family unavailable,設置為false時則程序可以正常運行:

System.setProperty("java.net.preferIPv4Stack", "true");
Socket socket = new Socket("::1", 80); // 訪問IPv6地址::1(相當於IPv4的127.0.0.1)的80端口會拋出異常

當TCP服務器java.net.preferIPv4Stack設置為true時,通過IPv6訪問就會訪問不通。 

在正常情況下,Tomcat或者Jetty等Java服務器啟動后,可以使用瀏覽器通過IPv4地址http://127.0.0.1:8080或IPv6地址http://[::1]:8080兩種方式訪問,此時通過lsof -i:8080命令可以看到對應進程的Type為IPv6:
lsof命令lsof命令

如果加上JVM參數-Djava.net.preferIPv4Stack=true啟動,此時通過lsof -i:8080命令可以看到對應進程的Type為IPv4:
lsof命令lsof命令
此時通過IPv6地址http://[::1]:8080將無法訪問,僅可通過IPv4地址http://127.0.0.1:8080訪問。

java.net.preferIPv6Addresses(默認值false)

官方文檔解釋:

By default, IPv4 addresses are preferred over IPv6 addresses, for example, when querying the name service (for instance, DNS service), IPv4 addresses would be returned ahead of IPv6 addresses.

java.net.preferIPv6Addresses為默認值false時,IPv4地址會優先使用,例如在DNS通過域名查詢IP地址時,會優先使用IPv4地址,反之設為true,則會優先使用IPv6地址。

Google目前支持IPv4和IPv6,可以host命令查看域名www.google.comDNS解析的IPv4和IPv6地址:

host www.google.com
> www.google.com has address 66.220.146.94
> www.google.com has IPv6 address 2404:6800:4008:803::2004

默認情況下會優先使用IPv4地址: 

System.out.println(InetAddress.getByName("www.google.com"));

輸出: 

www.google.com/66.220.146.94

java.net.preferIPv6Addresses設置為true時會優先使用IPv6地址: 

System.setProperty("java.net.preferIPv6Addresses", "true");
System.out.println(InetAddress.getByName("www.google.com"));

輸出: 

www.google.com/2404:6800:4008:803:0:0:0:2004

另外,通過InetAddress.getLocalHost()方法返回本機IP地址,最終返回的是IPv4還是IPv6地址,也會由java.net.preferIPv6Addresses的值來決定。 


免責聲明!

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



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