如何将 IPv6 地址转换为二进制字符串?

How to convert an IPv6 address to a binary string?

如何将 IPv6 地址转换为二进制字符串?

示例:

IPv6:    2001:0db8:85a3:0000:0000:8a2e:0370:7334
Binary:  0010000000000001 0000110110111000 1000010110100011 0000000000000000 0000000000000000 1000101000101110 0000001101110000 0111001100110100 

我想在 Java 中执行此操作。这是我失败的尝试(我不要求任何与此尝试相关的解决方案):

用我比较熟悉的C++实现:

#include <iostream>
#include <string>

#define _BSD_SOURCE
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

std::string toBinary(unsigned long int decimalIpV6)
{
    std::string r;
    while(decimalIpV6!=0) {r=(decimalIpV6%2==0 ?"0":"1")+r; decimalIpV6/=2;}
    return r;
}

unsigned long int ipV6toDecimal(std::string binaryString) {
    struct sockaddr_in antelope;    
    inet_aton(binaryString.c_str(), &antelope.sin_addr); // store IP in antelope
    // and this call is the same as the inet_aton() call, above:
    antelope.sin_addr.s_addr = inet_addr(binaryString.c_str());
    return antelope.sin_addr.s_addr;
}

int main() {
    std::string ipv6 = "192.168.0.0";
    unsigned long int ipv6decimal= ipV6toDecimal(ipv6);
    std::cout << toBinary(ipv6decimal) << std::endl;
    return 0;
}

有错误并产生错误结果(“1010100011000000”)。


PS: 有一个 IPv6 到二进制的计算器 online,这可能对你测试有帮助。

试试这个解决方案:

String ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
String[] spl = ipv6.split(":");
String result = "", del = "";
for (String s : spl) {
    result += del
            + String.format("%16s", new BigInteger(s, 16).toString(2)).replace(' ', '0');
    del = " ";
}
System.out.println(result);

如果您使用的是 Java 8,您可以使用:

String result = Stream.of(ipv6.split(":"))
      .map(s -> String.format("%16s", new BigInteger(s, 16).toString(2)).replace(' ', '0'))
      .collect(Collectors.joining(" "));

输出

0010000000000001 0000110110111000 1000010110100011 0000000000000000 0000000000000000 1000101000101110 0000001101110000 0111001100110100

你也可以这样做:

String ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
String result = "";
for (String s : ipv6.split(":")) {
    int value = Integer.parseInt(s, 16);
    result += String.format("%16s", Integer.toBinaryString(value)).replace(' ', '0') + " ";
}

System.out.println(result);

输出:

0010000000000001 0000110110111000 1000010110100011 0000000000000000 0000000000000000 1000101000101110 0000001101110000 0111001100110100 

编辑

当给定的 IPv6 地址被压缩时,先前的解决方案将不起作用。例如 3210:0000:0000:0000:0000:0000:0000:0000 可以缩短为 3210:: 并且值得一提的是,在这些情况下,如果我们不首先处理这个问题,那么到目前为止提出的解决方案将无法工作。要解决该问题,您可以这样做:

String ipv6CompressedAddress = "3210::";
Inet6Address ipv6Address = (Inet6Address) Inet6Address.getByName(ipv6CompressedAddress);
String ipv6 = ipv6Address.getCanonicalHostName(); // 3210:0:0:0:0:0:0:0

这里我使用 Java's IPv6 representation class Inet6Address 来获取压缩率较低的 IP 地址。然后我们可以使用前面展示的方法将其转换为二进制。

open-source IPAddress Java library 可以生成许多不同的字符串格式,其中一种是二进制字符串。免责声明:我是 IPAddress 库的项目经理。

String str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";

IPAddressString addrStr = new IPAddressString(str);
IPAddress addr  = addrStr.getAddress();
String binaryStr = addr.toBinaryString();
System.out.println(binaryStr);

输出:

00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110100

请注意,这处理了表示 IPv6 地址的各种不同方式(例如使用压缩段,或使用嵌入式 IPv4 作为最终段)。另请注意,该代码同样适用于 IPv4 地址。