为什么 Java 将某些 IPv6 地址解释为 IPv4?

Why does Java interpret some IPv6 addresses as IPv4?

为什么使用 InetAddress.getByName 时某些 IPv6 地址会转换为 IPv4 地址?

例如,我希望这两个地址::f:f:f::ffff:f:f都转换为Inet6Address

然而,这个 ::ffff:f:f 变成了 Inet4Address

import java.net.InetAddress;
class Main {
  public static void main(String[] args) throws Exception {
    // Interpreted as IPv6
    var address = InetAddress.getByName("::f:f:f");
    System.out.println(address); // /0:0:0:0:0:f:f:f
    System.out.println(address.getClass()); // class java.net.Inet6Address
    
    // Interpreted as IPv4
    address = InetAddress.getByName("::ffff:f:f");
    System.out.println(address); // /103.30.217.152
    System.out.println(address.getClass()); // class java.net.Inet4Address
  }
}

::ffff:0:0/96 范围内的 IPv6 地址是 IPv4 映射的 IPv6 地址。这是在 IPv6 寻址格式中表示 IPv4 地址的特殊范围,因此这些实际上是 IPv4 地址,而不是 IPv6 地址。这在 RFC 4291, IP Version 6 Addressing Architecture:

中有解释

2.5.5.2. IPv4-Mapped IPv6 Address

A second type of IPv6 address that holds an embedded IPv4 address is defined. This address type is used to represent the addresses of IPv4 nodes as IPv6 addresses. The format of the "IPv4-mapped IPv6 address" is as follows:

   |                80 bits               | 16 |      32 bits        |
   +--------------------------------------+--------------------------+
   |0000..............................0000|FFFF|    IPv4 address     |
   +--------------------------------------+----+---------------------+

See [RFC4038] for background on the usage of the "IPv4-mapped IPv6 address".