IP范围转IP掩码

java 复制代码
package com.chun.test;

/**
 * @author chun
 * @date 2025/4/11 11:18
 */
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class IpRangeCalculator2 {

    public static List<String> calculateCIDR(String startIp, String endIp) {
        try {
            BigInteger start = ipToBigInteger(startIp);
            BigInteger end = ipToBigInteger(endIp);
            int bits = getIPVersion(startIp);

            List<String> result = new ArrayList<>();

            if (start.compareTo(end) > 0) {
                return result;
            }

            while (start.compareTo(end) <= 0) {
                // 1. 计算当前可用的最大CIDR块
                int maxPrefix = findMaxPrefix(start, end, bits);
                String cidr = bigIntegerToIp(start, bits) + "/" + maxPrefix;
                result.add(cidr);

                // 2. 计算该CIDR块的结束地址并更新start
                BigInteger blockSize = BigInteger.ONE.shiftLeft(bits - maxPrefix);
                start = start.add(blockSize);
            }

            return result;
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    // 辅助方法:找到从start开始的最大CIDR前缀
    private static int findMaxPrefix(BigInteger start, BigInteger end, int bits) {
        BigInteger range = end.subtract(start).add(BigInteger.ONE);
        int maxShift = range.bitLength() - 1;
        if (maxShift < 0) maxShift = 0;

        for (int shift = maxShift; shift >= 0; shift--) {
            BigInteger size = BigInteger.ONE.shiftLeft(shift);
            if (size.compareTo(range) > 0) continue;

            // 检查地址是否对齐
            BigInteger mask = size.subtract(BigInteger.ONE);
            if (start.and(mask).equals(BigInteger.ZERO)) {
                return bits - shift;
            }
        }
        return bits; // 单个IP(/32或/128)
    }

    // IP转换方法(支持v4/v6)
    private static BigInteger ipToBigInteger(String ip) throws UnknownHostException {
        InetAddress address = InetAddress.getByName(ip);
        byte[] bytes = address.getAddress();
        return new BigInteger(1, bytes);
    }

    // 判断IP类型
    private static int getIPVersion(String ip) {
        return ip.contains(":") ? 128 : 32;
    }

    // 转换回IP字符串
    private static String bigIntegerToIp(BigInteger ip, int bits) throws UnknownHostException {
        byte[] bytes;
        if (bits == 32) { // IPv4
            bytes = ip.toByteArray();
            byte[] v4Bytes = new byte[4];
            System.arraycopy(bytes, Math.max(bytes.length - 4, 0), v4Bytes, 0, 4);
            return InetAddress.getByAddress(v4Bytes).getHostAddress();
        } else { // IPv6
            bytes = ip.toByteArray();
            byte[] v6Bytes = new byte[16];
            System.arraycopy(bytes, Math.max(bytes.length - 16, 0), v6Bytes, 0, bytes.length);
            return Inet6Address.getByAddress(v6Bytes).getHostAddress();
        }
    }

    public static void main(String[] args) {
        // IPv4测试
        System.out.println(calculateCIDR("192.168.0.127", "192.168.0.127"));
        // 输出: [192.168.0.0/30, 192.168.0.4/31]

        // IPv6测试
        System.out.println(calculateCIDR("2001:db8::8001", "2001:db8::fffa"));
        // 输出: [2001:db8::/126, 2001:db8::4/128]
    }
}

验证

java 复制代码
package com.chun.test;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;

/**
 * @author chun
 * @date 2025/4/11 11:46
 */
public class IPMaskCalculator {
    // 验证方法:打印每个CIDR的实际范围
    public static void printCIDRRange(List<String> cidrs) {
        for (String cidr : cidrs) {
            try {
                String[] parts = cidr.split("/");
                String ip = parts[0];
                int prefix = Integer.parseInt(parts[1]);

                int bits = getIPVersion(ip);
                BigInteger start = ipToBigInteger(ip);
                BigInteger mask = calculateMask(prefix, bits);

                // 计算CIDR范围
                BigInteger network = start.and(mask);
                BigInteger broadcast = network.add(mask.not().and(BigInteger.ONE.shiftLeft(bits).subtract(BigInteger.ONE)));

                System.out.printf("%-20s => %s - %s%n",
                        cidr,
                        bigIntegerToIp(network, bits),
                        bigIntegerToIp(broadcast, bits));
            } catch (Exception e) {
                System.out.println("Invalid CIDR: " + cidr);
            }
        }
    }

    // 计算网络掩码
    private static BigInteger calculateMask(int prefix, int bits) {
        return BigInteger.ONE.shiftLeft(bits)
                .subtract(BigInteger.ONE)
                .shiftLeft(bits - prefix)
                .and(BigInteger.ONE.shiftLeft(bits).subtract(BigInteger.ONE));
    }

    // 以下是复用之前的转换方法
    private static BigInteger ipToBigInteger(String ip) throws UnknownHostException {
        InetAddress address = InetAddress.getByName(ip);
        byte[] bytes = address.getAddress();
        return new BigInteger(1, bytes);
    }

    private static int getIPVersion(String ip) {
        return ip.contains(":") ? 128 : 32;
    }

    private static String bigIntegerToIp(BigInteger ip, int bits) throws UnknownHostException {
        byte[] bytes = ip.toByteArray();
        if (bits == 32) { // IPv4
            byte[] v4Bytes = new byte[4];
            System.arraycopy(bytes, Math.max(bytes.length - 4, 0), v4Bytes, 0, 4);
            return InetAddress.getByAddress(v4Bytes).getHostAddress();
        } else { // IPv6
            byte[] v6Bytes = new byte[16];
            System.arraycopy(bytes, Math.max(bytes.length - 16, 0), v6Bytes, 0, bytes.length);
            return Inet6Address.getByAddress(v6Bytes).getHostAddress();
        }
    }

    // 测试验证
    public static void main(String[] args) {
        // IPv4测试
        System.out.println("IPv4 Test:");
        printCIDRRange(Arrays.asList("192.168.0.127/32"));

        // IPv6测试
        System.out.println("\nIPv6 Test:");
        printCIDRRange(Arrays.asList(
                "2001:db8::/113", "2001:db8::8000/114", "2001:db8::c000/115", "2001:db8::e000/116",
                "2001:db8::f000/117", "2001:db8::f800/118", "2001:db8::fc00/119", "2001:db8::fe00/120",
                "2001:db8::ff00/121", "2001:db8::ff80/122", "2001:db8::ffc0/123", "2001:db8::ffe0/124",
                "2001:db8::fff0/125", "2001:db8::fff8/126", "2001:db8::fffc/127", "2001:db8::fffe/128"
        ));
    }
}

CIDR转换掩码

java 复制代码
package com.chun.test;

/**
 * @author chun
 * @date 2025/4/14 16:37
 */
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class CidrConverter {

    public static String cidrToMask(int cidr) {
        if (cidr < 0 || cidr > 128) {
            throw new IllegalArgumentException("CIDR must be between 0 and 128");
        }

        if (cidr <= 32) {
            // IPv4 处理(使用位运算)
            long maskLong = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL;
            int maskInt = (int) maskLong;
            int b1 = (maskInt >> 24) & 0xFF;
            int b2 = (maskInt >> 16) & 0xFF;
            int b3 = (maskInt >> 8) & 0xFF;
            int b4 = maskInt & 0xFF;
            return String.format("%d.%d.%d.%d", b1, b2, b3, b4);
        } else {
            // IPv6 处理(使用 Inet6Address)
            byte[] maskBytes = new byte[16];
            int fullBytes = cidr / 8;
            int remainingBits = cidr % 8;

            // 填充完整的 0xFF 字节
            Arrays.fill(maskBytes, 0, fullBytes, (byte) 0xFF);

            // 处理剩余位
            if (remainingBits > 0 && fullBytes < 16) {
                maskBytes[fullBytes] = (byte) (0xFF << (8 - remainingBits));
            }

            try {
                Inet6Address mask = (Inet6Address) InetAddress.getByAddress(maskBytes);
                return mask.getHostAddress().toLowerCase();
            } catch (UnknownHostException e) {
                throw new RuntimeException("Invalid IPv6 mask generation", e);
            }
        }
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(cidrToMask(32));   // 输出 255.255.255.255
        System.out.println(cidrToMask(28));   // 输出 255.255.255.255
        System.out.println(cidrToMask(29));   // 输出 255.255.255.255
        System.out.println(cidrToMask(30));   // 输出 255.255.255.255
        System.out.println(cidrToMask(31));   // 输出 255.255.255.255
        System.out.println(cidrToMask(24));   // 输出 255.255.255.0
        System.out.println(cidrToMask(0));    // 输出 0.0.0.0
        System.out.println(cidrToMask(128));  // 输出 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
        System.out.println(cidrToMask(64));   // 输出 ffff:ffff:ffff:ffff::
        System.out.println(cidrToMask(72));   // 输出 ffff:ffff:ffff:ffff:ff00::
        System.out.println(cidrToMask(127));  
        System.out.println(cidrToMask(126));  
        System.out.println(cidrToMask(125));  
        System.out.println(cidrToMask(124));  
        System.out.println(cidrToMask(65));   
        System.out.println(cidrToMask(66));   
        System.out.println(cidrToMask(67));   
        System.out.println(cidrToMask(68));   
        System.out.println(cidrToMask(69));   
    }
}
相关推荐
wyhwust7 分钟前
idea出现tomcat不能正确部署的问题--解决方案
java·ide·intellij-idea
vx1530278236213 分钟前
‌CDGP|数据治理:探索企业数据有序与安全的解决之道
大数据·运维·网络·cdgp·数据治理
带刺的坐椅21 分钟前
FastMCP(python)和 SolonMCP(java)的体验比较(不能说一样,但真的很像)
java·python·solon·mcp·fastmcp
_只道当时是寻常30 分钟前
【网络入侵检测】基于源码分析Suricata的IP分片重组
网络·安全·网络安全·安全威胁分析
一勺菠萝丶37 分钟前
深入浅出:Spring Boot 中 RestTemplate 的完整使用指南
java·spring boot·后端
努力的搬砖人.41 分钟前
Java 线程池原理
java·开发语言
1024小神1 小时前
tauri-plugin-store 这个插件将数据存在本地电脑哪个位置
运维·服务器
Fanmeang1 小时前
BGP选路原则实验案例
运维·网络·华为·bgp·路由选路·路由选路原则·route-policy
有梦想的攻城狮1 小时前
SpEL(Spring Expression Language)使用详解
java·后端·spring·spel
Lw老王要学习1 小时前
Linux架构篇、第三章_2_Linux服务器监控与NGINX优化
linux·运维·服务器·nginx·架构·云计算