如何将IPv4地址转换为IPv6

24

这个可能吗?你如何将ipv4转换为ipv6地址?

以下是一些示例:

0.0.0.0   -> ::
127.0.0.1 -> ::1

我正在寻找Java的解决方案。

谢谢。

6个回答

32

没有有意义的IPv4到IPv6映射。像0.0.0.0和127.0.0.1这样的东西是规范中的特例,因此它们具有等效的含义。但是,给定一个IPv4地址,它并不能告诉你它具体的IPv6地址是什么。您可以使用DNS查找来查看给定的IP地址是否解析为一个主机,该主机除了IPv4地址外还解析为IPv6地址,但DNS服务器必须配置以支持该特定设备。


12
在双栈系统中,实际上存在一个从IPv4地址映射到IPv6地址的过程,在::ffff:XXXX:XXXX地址空间中进行;这通常显示为“::ffff:192.168.1.1”--因此在IPv6地址空间中存在IPv4地址的有意义表示。 - Doktor J
2
@DoktorJ,我认为那不是问题所在。我想请求的是一个正确的IP6地址,而不是在IP6堆栈上引用IP4地址的方法。 - Yishai
2
@DoktorJ 但是,除非您拥有某种路由设施,否则这种映射并不能真正帮助您。 - glglgl
3
我不同意语气:我曾在几个应用程序中看到IPv4地址映射到IPv6,其中开发者想要将所有地址统一格式以便排序、搜索等目的,而且没有例外的是::ffff:0:0/96。我不知道它是否严格有意义,但肯定很有用。维基百科在权衡利弊方面做得很好:https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses - Tim Bray

22

混合双栈IPv6/IPv4实现通常支持一种特殊的地址类别,即IPv4映射地址。要了解更多,请查看以下链接:

http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses

要将IPv4转换为映射IPv6,您可以使用以下内容:

String ip = "127.0.0.1"; 
String[] octets = ip.split("\\.");
byte[] octetBytes = new byte[4];
 for (int i = 0; i < 4; ++i) {
            octetBytes[i] = (byte) Integer.parseInt(octets[i]);
}

byte ipv4asIpV6addr[] = new byte[16];
ipv4asIpV6addr[10] = (byte)0xff;
ipv4asIpV6addr[11] = (byte)0xff;
ipv4asIpV6addr[12] = octetBytes[0];
ipv4asIpV6addr[13] = octetBytes[1];
ipv4asIpV6addr[14] = octetBytes[2];
ipv4asIpV6addr[15] = octetBytes[3];

同时查看这个


7

在IPv6中,曾经有一个保留的地址空间用于存储IPv4地址,只需要在IPv4地址前面添加96个0位即可。例如:192.168.10.13 -> ::C0A8:0A0D。但是我知道现在已经不建议使用这种方法了,也不再提供直接转换。


8
我认为仍然存在未被废弃的IPv4映射IPv6地址。在此方案中,您的示例将是::ffff:c0a8:0a0d。其中带有0的那个被称为IPv4兼容IPv6地址。 - Tony van der Peet

4

IPv6兼容IPv4。

一个IPv4地址:例如192.168.99.1

步骤1 >

将第一个八位数(192)除以16(因为Hex是Base-16) 即: 192/16 = 12 次,余数为0 - 用十六进制表示的12是C - 用十六进制表示的0是0 因此,192在HEX中表示为C0

步骤2 >

用第二个八位数(168)重复步骤1, 即: 168/16 = 10次,余数为8,因为10*6 = 160, - 用十六进制表示的10是A - 用十六进制表示的8是8 因此,168在HEX中表示为A8

步骤3 >

重复规则!!! 第三个八位数(99) 即: 99/16 = 6次,余数为3 - 用十六进制表示的6是6 - 用十六进制表示的3是3 因此,99在HEX中表示为63

步骤4 >

最后一个八位数 即: 1/16 = 0次,余数为1 - 用十六进制表示的0是0 - 用十六进制表示的1是1 因此,1在HEX中表示为01

因此,192.168.99.1的IPv4地址,在IPv6地址部分的表示方式应该是C0A8:6301。然而,您必须使用小写,并添加所有缺失的字节IPv6,因此正确的代码是:

::c0a8:6301

或者,您可以始终接受一个语法:

::192.168.99.1

因此,最终IPv6地址可以是旧地址,在旧地址前面加上::字符。


::192.168.99.1 的表示已经过时,必须改为 `::ffff:192.168.99.1'。请参阅Wikipedia - IPv4-mapped IPv6 addresses - Ingo

3
有许多方法可以将IPv4映射到IPv6。对于大多数这样的方法,转换后的IPv4地址被放置在16字节IPv6地址的低4字节中。 IPAddress Java库具有许多帮助将IPv4转换为IPv6的常见方法的方法。免责声明:我是该库的项目经理。
例如,给定IPv4地址,您可以使用IPv6映射转换将其转换为IPv6,如下所示:
IPv6Address ipv6Address = new IPAddressString("1.2.3.4").getAddress().toIPv4().
    getIPv4MappedAddress();
System.out.println(ipv6Address); // ::ffff:102:304
System.out.println(ipv6Address.toMixedString()); // ::ffff:1.2.3.4

通过IPv6Address实例,您可以检查地址是否为IPv4映射、IPv4兼容、IPv4转换等(这些是IPv6表示IPv4地址的许多可能方式之一)。然后,您可以转换回IPv4。

if(addr.isIPv4Compatible() || addr.isIPv4Mapped()) {
    IPv4Address derivedIpv4Address = ipv6Address.getEmbeddedIPv4Address();
    byte ipv4Bytes[] = ipv4Address.getBytes();
    ...
 }

-2

这是Javascript中的转换代码

/** IPV4 CIDR to IPV6 CIDR conversion **/
function covertIPv6(x){
let ipV4 = x;
let address = ipV4.split('/');
let classValues = [];

if(address.length){
  classValues = address[0].split('.');
}
if(classValues.length){  
  let str = classValues.reduce((acc, val, ind)=>{
    let mod = +val >= 16 ? +val%16 : +val;
    let divider = +val >= 16 ? (val-mod)/16 : 0;
    const hexaCode = (hexaVal)=>{
      switch(hexaVal){
      case 10:
        hexaVal = 'A';
        break;
      case 11:
        hexaVal = 'B';
        break;
      case 12:
        hexaVal = 'C';
        break;
      case 13:
        hexaVal = 'D';
        break;
      case 14:
        hexaVal = 'E';
        break;
      case 15:
        hexaVal = 'F';
        break;
      default:
        hexaVal = hexaVal;
        break;
    }
      return hexaVal;
    }
    mod = hexaCode(mod);
    divider = hexaCode(divider);
    return ind === 1 ? `${acc}${divider}${mod}:`:`${acc}${divider}${mod}`
  },'')
  return `2002:${str}::/${address[1]}`;
}
  return "Invalid Address";
}

// Run the function

console.log(covertIPv6("0.0.0.0/12"));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接