4

我有一个如下所示的 ip 数组,我想将其转换为最小的 cidr 子网列表。Java中是否有用于该库的库?

例如:

1.1.3.0
1.1.3.1
1.1.3.2
1.1.3.3
..
1.1.3.254
1.1.3.255
1.2.3.0
1.2.3.1
1.2.3.2
1.2.3.3
..
1.2.3.254
1.2.3.255
1.3.3.0
1.3.3.1
1.3.3.2
1.3.3.3
..
1.3.3.128
1.3.3.129

转换成

1.1.3.0/24
1.2.3.0/24
1.3.3.0/25
1.3.3.128/31

提前致谢。

4

3 回答 3

2

我不知道Java中是否有可用的库。确实,我对 Java 知之甚少 :) 但如果有帮助的话,我可以给你一个解决问题的算法。

1)将ip地址转换成整数对,其中第一个整数是ip地址的二进制表示(abcd -> a << 24 + b << 16 + c << 8 + d),第二个整数是32 (也就是说,最初每个地址都是它自己的子网 [1])。

2) 对列表进行排序。

3) 现在扫描排序列表,从第二对开始。对于每一对,如果你可以将它与前一对结合起来,那么就这样做并继续尝试,直到尽可能长时间地结合。两对[base1, bits1]and[base2, bits2]可以组合 ifbits1 == bits2base2 ^ base1 == 1 << (32 - bits1). 在这种情况下,组合是[base1, bits1 - 1]

4) 最后,将这些对转换回 CIDR 表示法:第一个整数是子网的基数(转换回点分十进制时),第二个整数是位宽。

第 2 步和第 3 步都是O(n log n)

脚注 1:在您的示例中,您没有包含最后一个字节 0 的地址,这意味着我的算法将在您的测试用例中失败。您必须将它们添加到列表中。这一点揭示了 CIDR 子网定义中一个微妙但重要的细节:从技术上讲,可能的最小子网是 /30,因为该范围的第一个和最后一个 ip 都被保留。因此 /31 将没有有效的 IP 地址。但是,人们经常使用术语 CIDR 子网来表示“识别一组 IP 地址的位掩码”,就像它们用作过滤器表达式一样。

于 2012-09-20T17:08:09.963 回答
1

Java中有一个可用的库。开源 IPAddress Java 库具有将地址合并到前缀块子网的方法。免责声明:我是 IPAddress 库的项目经理。

以下方法“合并”显示了代码,依赖于库中的方法 mergeToPrefixBlocks:

static String[] merge(List<String> strs) {
    // convert first to address
    IPAddress first = new IPAddressString(strs.get(0)).getAddress();
    // convert remaining to address
    IPAddress others[] = strs.subList(1, strs.size()).stream().map(str -> new IPAddressString(str).getAddress()).toArray(IPAddress[]::new);
    // merge them all
    IPAddress[] blocks = first.mergeToPrefixBlocks(others);
    // convert back to strings
    return Arrays.stream(blocks).map(block -> block.toString()).toArray(String[]::new);
}

可以使用您的一组示例地址来演示该方法,如以下代码所示:

ArrayList<String> strs = new ArrayList<>();
String firstPref = "1.1.3.";
String secondPref = "1.2.3.";
String thirdPref = "1.3.3.";
for(int i = 0; i <= 255; i++) {
    strs.add(firstPref + i);
    strs.add(secondPref + i);
}           
for(int i = 0; i <= 129; i++) {
    strs.add(thirdPref + i);
}
String result[] = merge(strs);
System.out.println("blocks are " + Arrays.asList(result));

输出是:

blocks are [1.3.3.128/31, 1.3.3.0/25, 1.1.3.0/24, 1.2.3.0/24]
于 2019-03-25T04:40:14.413 回答
-6

试试看:

public class Test {
    public static void main(String[] args) {
        String[] ipArray1 = new String[]{"1.1.3.1", "1.1.3.3", "1.1.3.2", "1.3.3.254"};
        String[] ipArray2 = new String[ipArray1.length];
        for(int i=0; i < ipArray1.length; i++) {
            String temp = ipArray1[i];
            ipArray2[i] = temp.substring(0,6) + "0/24";
        }
        for(String  ip : ipArray2) {
            System.out.println(ip);
        }
    }
}

输出 :

    1.1.3.0/24
    1.1.3.0/24
    1.1.3.0/24
    1.3.3.0/24
于 2012-09-20T15:29:14.840 回答