用于将长IPv6地址转换为压缩形式的Java库

时间:2010-09-21 13:46:39

标签: java ipv6

我想知道,是否有一个库可用于将长IPv6地址(例如2002:9876:57AB:0000:0000:0000:0000:0001)的表示转换为压缩的IPv6表格(在这种情况下:2002:9876:57AB :: 1)。

我无法找到这样的图书馆。该库不应使用任何IP Api,不得进行网络连接。

我已经尝试了

return Inet6Address.getByName(longAdress).toString();

但这只是将4个零替换为1(在本例中为2002:9876:57AB:0:0:0:0:1)。

有什么建议吗?

4 个答案:

答案 0 :(得分:5)

java-ipv6是一个非常体面的图书馆。它还可以很好地处理地址范围。

答案 1 :(得分:3)

public class Ipv6AddressCompressor {
    public static String getCompressedAddress(String longAddress) throws UnknownHostException {
        longAddress = Inet6Address.getByName(longAddress).getHostAddress();
        return longAddress.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
    }
}

这可以保护您免受无效地址的攻击(抛出UnknownHostException),并将正确压缩尾随的ipv4地址(即0:0:0:0:0:0:255.255.255.255 - > :: FFFF:FFFF)。这也可以防止已压缩的地址。

答案 2 :(得分:1)

The open-source IPAddress Java library可以进行ip地址解析并生成各种字符串。免责声明:我是该图书馆的项目经理。

示例代码:

    String ipv6 = "2002:9876:57AB:0000:0000:0000:0000:0001";
    try {
        IPAddressString str = new IPAddressString(ipv6);
        IPAddress addr = str.toAddress();
        String compressed = addr.toCompressedString();
        System.out.println(compressed); //
    } catch(IPAddressStringException e) {
        //e.getMessage has validation error
    }

输出:

2002:9876:57ab::1

答案 3 :(得分:0)

您可以尝试使用此代码。它可能比正则表达式更好(不是我对它进行了基准测试,或者其他任何东西)。它也经过了很好的测试。

请注意,您需要使用IP地址的数字表示(在byte[]中)。要获得它,如果需要解析主机名,可以执行InetAddress.getByName(ip).getAddress(),或者在没有主机解析的情况下使用sun实用程序类IPAddressUtil.textToNumericFormatV6(ip)从IP地址进行解析。

private static final char[] ipv6conseqZeroFiller = { ':', ':' };
private static final char ipv6hextetSeparator = ':';

/*
 * Convert numeric IPv6 to compressed format, where
 * the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
 */
public static String ipv6toCompressedForm(byte[] src) {
    assert src.length == 16;
    //Find the longest sequence of 0's 
    int cmprHextet = -1; //start of compressed region (hextet index)
    int cmprSize = 0; //length of compressed region
    for (int hextet = 0; hextet < 8;) {
        int curByte = hextet * 2;
        int size = 0;
        while (curByte < src.length && src[curByte] == 0
                && src[curByte + 1] == 0) {
            curByte += 2;
            size++;
        }
        if (size > cmprSize) {
            cmprHextet = hextet;
            cmprSize = size;
        }
        hextet = (curByte / 2) + 1;
    }
    if (cmprHextet == -1 || cmprSize < 2) {
        //No compression can be applied
        return ipv6toStr(src);
    }
    StringBuilder sb = new StringBuilder(39);
    ipv6toStr(sb, src, 0, cmprHextet);
    sb.append(ipv6conseqZeroFiller);
    ipv6toStr(sb, src, cmprHextet + cmprSize, 8);
    return sb.toString();
}

/*
 * Convert numeric IPv6 to standard (non-compressed) format.
 *
 * Borrowed from Inet6Address.java #numericToTextFormat(byte[])
 * Changed StringBuffer -> StringBuilder and ":" -> ':' for performance.
 */
public static String ipv6toStr(byte[] src) {
    assert src.length == 16;
    StringBuilder sb = new StringBuilder(39);
    ipv6toStr(sb, src, 0, 8);
    return sb.toString();
}

private static final void ipv6toStr(StringBuilder sb, byte[] src,
        int fromHextet, int toHextet) {
    for (int i = fromHextet; i < toHextet; i++) {
        sb.append(Integer.toHexString(((src[i << 1] << 8) & 0xff00)
                | (src[(i << 1) + 1] & 0xff)));
        if (i < toHextet - 1) {
            sb.append(ipv6hextetSeparator);
        }
    }
}