在 Java 中將 IPv4 位址轉換為 IPv6 位址
1. 概述
網際網路協定第六版(IPv6),定義於 RFC 2460,是最新一代的網際網路協定。它取代了有限的 IPv4 位址空間。然而,IPv6 與 IPv4 並不直接相容。因此,使用不同協定的設備經常會遇到相容性問題。
為了解決這個問題,現代系統採用了雙棧、隧道和轉換等技術。因此,這些方法使系統能夠在支援 IPv4 的同時支援 IPv6。然而,它們主要在網路層(第三層)工作。
在許多情況下,開發人員需要一種方法來以 IPv6 相容的格式表示 IPv4 位址。因此,他們會編寫程式碼來映射兩種格式之間的資料。
在本教程中,我們將學習如何使用 Java 將 IPv4 位址轉換為 IPv6 位址。
2. 轉換是什麼意思?
實際上, IPv4 和 IPv6 之間沒有直接的轉換關係。這兩種協議在結構和設計上都存在差異。
另一種常見的做法是將 IPv4 位址嵌入到 IPv6 位址中。這種格式稱為 IPv4 對映的 IPv6 位址。
此外,我們還有其他表示方法。然而,並非所有方法都已成為標準。例如,與 IPv4 相容的 IPv6 位址現已棄用。同樣, NAT64和6to4只是過渡方法,而非真正的轉換。
那麼,讓我們來看看如何在 Java 中實作上述技術。
3. Java 實現
本質上,Java 提供了用於處理 IP 位址的內建類別。 InetAddress InetAddress同時支援 IPv4 和 IPv6。
3.1. 將 IPv4 位址轉換為 IPv6 對應位址
我們來看一個映射地址的例子。
為此,我們使用標準格式將 IPv4 位址轉換為 IPv6 格式:
::ffff:wxyz
在上述範例中, wxyz是目標 IPv4 位址:
String toIpv4MappedIpv6(String ipv4Address) throws UnknownHostException {
validateIpv4(ipv4Address);
return "::ffff:" + ipv4Address;
}
這個方法只是簡單地加入::ffff:前綴。這樣,我們就得到了一個有效的 IPv4 映射的 IPv6 位址。
3.2. IPv4 相容的 IPv6 位址
值得注意的是,與 IPv4 相容的 IPv6 位址格式已不再使用。不過,了解舊系統仍然很有幫助。
用十六進位表示法,這種類型的位址會將所有前導位元設為零。
我們再次以 IPv4 位址wxyz :
0000:0000:0000:0000:0000:0000:WWXX:YYZZ
也可以省略所有前導零來壓縮此位址:
::wxyz
此外,我們還可以看到它的具體實現方式:
String toIpv4CompatibleIpv6(String ipv4Address) throws UnknownHostException {
validateIpv4(ipv4Address);
return "::" + ipv4Address;
}
上述方法接受一個 IPv4 位址,並回傳一個 IPv6 位址。
因此,IPv4 位址192.0.2.33傳回 IPv4 相容的 IPv6 ::192.0.2.33.
3.3. NAT64 實現
NAT64 風格的轉換位址通常使用64:ff9b::/96前綴,後面緊跟著目標 IPv4 位址。
例如,形如wxyz的 IP 位址將獲得 NAT64 ID 64:ff9b::wxyz 。
實作程式碼與先前的版本相同:
String toNat64Ipv6(String ipv4Address) throws UnknownHostException {
validateIpv4(ipv4Address);
return "64:ff9b::" + ipv4Address;
}
因此,如果我們有一個 IPv4 位址192.0.2.33 ,則結果位址應該是64:ff9b::192.0.2.33 。
3.4. 6to4位址(隧道)
6to4是一種過渡方法。它將 IPv6 封包封裝在 IPv4 封包中。此外,為此,互聯網號碼分配機構 ( IANA ) 分配了2002::/16位址區塊。
例如,IPv4 位址192.0.2.4十六進位等效值為C000:0204 。在這種情況下, 6to4前綴變為2002:C000:0204::/48 。
16 bits (the base) + 32 bits (the IPv4) = 48 bits
因此,前綴2002::/16後面跟著32位元公共 IPv4 位址。
讓我們來看看它的 Java 實作:
String toSixToFourIpv6(String ipv4Address) throws UnknownHostException {
byte[] bytes = validateAndGetBytes(ipv4Address);
return String.format("2002:%02x%02x:%02x%02x::",
bytes[0] & 0xff,
bytes[1] & 0xff,
bytes[2] & 0xff,
bytes[3] & 0xff);
}
上述方法將每個 IPv4 位元組轉換為其十六進位表示形式。
最後,將結果附加到2002::/16前綴。
4. JUnit 測試
為了驗證類別方法,我們可以寫一個簡單的 JUnit 測試:
class Ipv4ToIpv6ConverterUnitTest {
private final Ipv4ToIpv6Converter converter = new Ipv4ToIpv6Converter();
@Test
void whenValidIpv4_thenReturnMappedIpv6() throws Exception {
String result = converter.toIpv4MappedIpv6("192.168.1.1");
assertEquals("::ffff:192.168.1.1", result);
}
}
因此,我們可以檢查輸出是否與預期值相符。同樣地,我們也可以為其他方法編寫測試。
5. 應用案例
IPv4 對應到 IPv6 位址有助於兩種協定在雙堆疊系統中協同工作。
如果使用者沒有雙棧支持,他們也可以使用隧道機制,例如6to4 。
同樣,我們也有像 NAT64 這樣的轉換器。它們也有助於 IPv4 設備和 IPv6 設備之間的互通性。
轉換的總體思路是使不同的協定能夠同步工作。
6. 結論
本文探討如何使用 Java 在 IPv4 和 IPv6 之間進行轉換。由於這兩種 IP 協定在結構和語意上都存在差異,我們無法真正將 IPv4 轉換為 IPv6。
因此,上述方法並不能將 IPv4 主機轉換為原生 IPv6 主機,而是提供了一種使系統能夠協同運作的方式。 Java 透過 InetAddress 和位元組處理等類別簡化了這個過程。
因此,應用程式可以有效率地支援這兩種位址格式。
本文的完整程式碼可 在 GitHub 上找到。