从给定的IP地址和子网掩码中获取所有IP地址

时间:2014-11-04 15:11:53

标签: java network-programming ip

在Java中,我需要获取给定IP网络包含的所有IP地址的列表。

例如让netowork为:192.168.5.0/24然后输出将是(192.168.5.0 ... 192.168.5.255)。

我可以想到以下方式,但它看起来很脏,有没有优雅的方式? InetAddress类中没有相同的功能。

  1. 从输入IP和子网掩码中获取网络IP。

    mask = (long)(0xffffffff) << (32-subnetMask);
    Long netIp = getLongfromIp(Inputip)& mask;
    
  2. 函数'getLongfromIp'包含来自 - How to convert string (IP numbers) to Integer in Java

    的代码
    1. 通过子网掩码获取主机数

      maxRange = (long)0x1<<(32-subnetMask);

    2. 通过在netIp中添加for i in (0 .. maxRange)来获取所有希望的地址

    3. 将ip从上一步转换为八位字符串。

    4. Ps:我确定IP地址只能在IPV4中。

4 个答案:

答案 0 :(得分:5)

回答我自己的问题,解决方案是使用 Apache commons.net

import org.apache.commons.net.util.*;

SubnetUtils utils = new SubnetUtils("192.168.1.0/24");
String[] allIps = utils.getInfo().getAllAddresses();
//appIps will contain all the ip address in the subnet

了解详情:Class SubnetUtils.SubnetInfo

答案 1 :(得分:1)

包含NetworkAddress和BroadcastAddress

import org.apache.commons.net.util.*;

 SubnetUtils utils = new SubnetUtils("192.168.1.0/28");
       utils.setInclusiveHostCount(true);

       String[] allIps = utils.getInfo().getAllAddresses();

答案 2 :(得分:0)

The IPAddress Java library以一种多态的方式同时支持IPv4和IPv6子网。免责声明:我是项目经理。

以下是示例代码,用于透明地列出IPv4或Ipv6子网的地址。子网可能会变得很大,尤其是使用IPv6时,子网会变得很大,并且尝试通过大型子网进行迭代是不明智的,因此iterateEdges的代码显示了如何仅通过子网中的起始地址和结束地址进行迭代。

show("192.168.10.0/24");
show("2001:db8:abcd:0012::/64");

static void show(String subnet) throws AddressStringException {
    IPAddressString addrString = new IPAddressString(subnet);
    IPAddress addr = addrString.toAddress();
    show(addr);
    System.out.println();
}

static void show(IPAddress subnet) {
    Integer prefix = subnet.getNetworkPrefixLength();
    IPAddress mask = subnet.getNetwork().getNetworkMask(prefix, false);
    BigInteger count = subnet.getCount();
    System.out.println("Subnet of size " + count + " with prefix length " + prefix + " and mask " + mask);
    System.out.println("Subnet ranges from " + subnet.getLower() + " to " + subnet.getUpper());
    if(count.compareTo(BigInteger.valueOf(256)) <= 0) {
        iterateAll(subnet);
    } else {
        iterateEdges(subnet);
    }
}

static void iterateAll(IPAddress subnet) {
    BigInteger count = subnet.getCount();
    BigInteger three = BigInteger.valueOf(3), currentCount = count;
    int i = 0;
    for(IPAddress addr: subnet.getIterable()) {
        if(i < 3) {
            System.out.println(++i + ": " + addr);
        } else if(currentCount.compareTo(three) <= 0) {
            System.out.println(count.subtract(currentCount) + ": " + addr);
        } else if(i == 3) {
            System.out.println("...skipping...");
            i++;
        }
        currentCount = currentCount.subtract(BigInteger.ONE);
    }
}

static void iterateEdges(IPAddress subnet) {
    int sample = 3;
    for(int i = -sample; i < sample; i++) {
        if(i < 0) {
            int increment = i + sample + 1;
            System.out.println(increment + ": " + subnet.getLower().increment(increment - 1));
        } else {
            if(i == 0) {
                System.out.println("...skipping...");
            }
            BigInteger count = subnet.getCount();
            int increment = i - sample + 1;
            System.out.println(count.add(BigInteger.valueOf(increment)) + ": " + subnet.getUpper().increment(increment));
        } 
    }
}

以下是输出:

Subnet of size 256 with prefix length 24 and mask 255.255.255.0
Subnet ranges from 192.168.5.0/24 to 192.168.5.255/24
1: 192.168.5.0/24
2: 192.168.5.1/24
3: 192.168.5.2/24
...skipping...
253: 192.168.5.253/24
254: 192.168.5.254/24
255: 192.168.5.255/24

Subnet of size 18446744073709551616 with prefix length 64 and mask ffff:ffff:ffff:ffff::
Subnet ranges from 2001:db8:abcd:12::/64 to 2001:db8:abcd:12:ffff:ffff:ffff:ffff/64
1: 2001:db8:abcd:12::/64
2: 2001:db8:abcd:12::1/64
3: 2001:db8:abcd:12::2/64
...skipping...
18446744073709551614: 2001:db8:abcd:12:ffff:ffff:ffff:fffd/64
18446744073709551615: 2001:db8:abcd:12:ffff:ffff:ffff:fffe/64
18446744073709551616: 2001:db8:abcd:12:ffff:ffff:ffff:ffff/64

如果您以地址开头,则可以使用toPrefixBlock()获取子网:

IPAddress addr = new IPAddressString("192.168.5.1/24").toAddress();
IPAddress subnet = addr.toPrefixBlock();
System.out.println(addr + " is from subnet " + subnet);

输出:

192.168.5.1/24 is from subnet 192.168.5.0/24

答案 3 :(得分:0)

以下内容与使用https://seancfoley.github.io/IPAddress/的Sean的回答(非常好!)相同,只是降低了信噪比:

subnetToIps("192.168.10.0/28");

    public void subnetToIps(String ipOrCidr) {
        IPAddressString addrString = new IPAddressString(ipOrCidr, IPAddressString.DEFAULT_VALIDATION_OPTIONS);
        IPAddress subnet = addrString.toAddress();
        System.out.println("Subnet ranges from " + subnet.getLower() + " to " + subnet.getUpper());

        int i = 0;
        for (IPAddress addr : subnet.getIterable()) {
            System.out.println(++i + ": " + addr);
        }
    }