Java/Kotlin 获取同子网所有 IP

Kotlin

fun InetAddress.getHost(): List {

    val bitMask = NetworkInterface.getByInetAddress(this)
            .interfaceAddresses[0].networkPrefixLength
    val netmask = (0xff_ff_ff_ff shl (32 - bitMask)).toInt()
    val ip = address[0].toLong() shl 24 or
            (address[1].toLong() shl 16 and (0xff shl 16)) or
            (address[2].toLong() shl 8 and (0xff shl 8)) or
            (address[3].toLong() and 0xff)
    val startIp = ip and netmask
    val hosts = mutableListOf()
    for (i in 1L until netmask.inv()) {
        val h = startIp or i
        if (h == ip){
            continue
        }
        hosts.add(startIp or i)
    }
    return hosts.map { InetAddress.getByName(ipToString(it)) }
}
private fun ipToString(address: Long): String {
    return (address ushr 24 and 0xFF).toString() + "." +
            (address ushr 16 and 0xFF) + "." +
            (address ushr 8 and 0xFF) + "." +
            (address and 0xFF)
}
fun main(){
    Inet4Address.getLocalHost().getHost().forEach {
        println(it.hostAddress)
    }
}

Java

    InetAddress localhost = Inet4Address.getLocalHost(); // 192.168.0.1/24
    NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localhost);
    
    int bitMask = networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength();   // 24
    int netmask = 0xff_ff_ff_ff << (32 - bitMask);  // 0xff_ff_ff_00
    byte[] ip4 = localhost.getAddress();    // [0xc0, 0xa8, 0x01, 0xa3]
    int ip = ip4[0] << 24 |
            ip4[1] << 16 & 0xff << 16 |
            ip4[2] << 8 & 0xff << 8 |
            ip4[3] & 0xff;  // 0xc0_a8_01_a3
    
    int startIp = ip & netmask; // 0xc0_a8_01_a3 & 0xff_ff_ff_00
    int endIp = ip | ~netmask; // 0xc0_a8_01_a3 | ~0xff_ff_ff_00
    
    List host = new ArrayList<>();
    // skip first and last, self
    for (int i = 1, c = ~netmask; i < c; i++) {
        int h = startIp | i;
        if (h == ip) continue;
        host.add(startIp | i);
    }
    System.out.printf("%08x %s%n", ip, ipToString(ip));
    System.out.printf("%08x %s%n", startIp, ipToString(startIp));
    System.out.printf("%08x %s%n", endIp, ipToString(endIp));
    for (Integer integer : host) {
        System.out.println(ipToString(integer));
    }

    static String ipToString(int address) {
        return (address >>> 24 & 0xFF) + "." +
                (address >>> 16 & 0xFF) + "." +
                (address >>> 8 & 0xFF) + "." +
                (address & 0xFF);
    }

通过掩码位计算子网掩码

掩: 掩盖, 表示你不必关注的东西. 码: 编码, 二进制. 位: 位置.

掩码位为 0-32 整数, 越大表示可划分的主机数量越少. 掩码位如何隐射成掩码呢? 如下例子, 假设掩码位是 24, 其中 24 可以看做是 32 位中从做往右数有几个 1, 那么 24 就是有 24 个 1, 剩余的都是 0.

11111111 11111111 11111111 00000000
FF FF FF 00
255 255 255 0

我们把第一列二进制数依次往下转换成 16 进制, 10 进制, 得到了最终掩码就是 255.255.255.0.

通过子网掩码计算子网 IP

int start = ip & subnetMask;
int end = ip | ~subnetMask;

将当前 IP 按位 子网掩码 即可得到最小 IP, 将当前 IP 按位 子网掩码按位 即可得到最大 IP.

子网掩码按位 既是子网 IP 数量.

你可能感兴趣的:(Java/Kotlin 获取同子网所有 IP)