You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写Java程序实现IPv6起始-结束地址转CIDR列表?

IPv6 Range to CIDR List in Java

Got it, converting an IPv6 address range to a list of CIDR blocks is totally doable by adapting the IPv4 logic you referenced—we just need to account for IPv6's 128-bit length and handle its hexadecimal formatting. Let's walk through how to implement this step by step.

Core Concept

The IPv4 approach relies on 32-bit integers to represent addresses, then uses a greedy algorithm to find the largest possible CIDR blocks that fit within the range. For IPv6, we'll use BigInteger to handle the 128-bit values (since Java doesn't have a native 128-bit integer type). The algorithm stays roughly the same:

  • Convert start and end IPv6 addresses to BigInteger values
  • Iterate from the start address, find the largest CIDR prefix that doesn't exceed the end address
  • Add that CIDR to the list, then move the start address to the end of that block
  • Repeat until the start address exceeds the end address

Step-by-Step Implementation

1. Convert IPv6 Address to BigInteger

First, we need a way to parse an IPv6 string into a BigInteger (and vice versa). We can use Java's Inet6Address class to handle parsing, then convert its byte array to a BigInteger:

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

public class IPv6ToCIDR {

    // Convert IPv6 string to BigInteger
    private static BigInteger ipv6ToBigInteger(String ipv6Str) throws UnknownHostException {
        InetAddress addr = InetAddress.getByName(ipv6Str);
        if (!(addr instanceof Inet6Address)) {
            throw new IllegalArgumentException("Not a valid IPv6 address");
        }
        byte[] bytes = addr.getAddress();
        return new BigInteger(1, bytes); // 1 ensures positive sign for the integer
    }

    // Convert BigInteger back to IPv6 string (handles compression like ::)
    private static String bigIntegerToIPv6(BigInteger bigInt) throws UnknownHostException {
        byte[] bytes = bigInt.toByteArray();
        // Ensure we have exactly 16 bytes for IPv6 (pad with leading zeros if needed)
        byte[] ipv6Bytes = new byte[16];
        if (bytes.length > 16) {
            // Copy the last 16 bytes to strip any leading sign byte
            System.arraycopy(bytes, bytes.length - 16, ipv6Bytes, 0, 16);
        } else {
            // Pad with leading zeros to fill 16 bytes
            System.arraycopy(bytes, 0, ipv6Bytes, 16 - bytes.length, bytes.length);
        }
        InetAddress addr = Inet6Address.getByAddress(ipv6Bytes);
        return addr.getHostAddress();
    }

2. Core CIDR Generation Logic

Next, the main method that generates the CIDR list. The key part is calculating the maximum prefix length we can use for the current start address without going beyond the end address:

public static List<String> getCIDRList(String startIp, String endIp) throws UnknownHostException {
        BigInteger start = ipv6ToBigInteger(startIp);
        BigInteger end = ipv6ToBigInteger(endIp);
        List<String> cidrList = new ArrayList<>();

        while (start.compareTo(end) <= 0) {
            // Start with the smallest possible block (prefix length 128) and work backwards
            int maxPrefix = 128;
            while (maxPrefix > 0) {
                BigInteger blockSize = BigInteger.ONE.shiftLeft(128 - maxPrefix);
                BigInteger networkMask = blockSize.subtract(BigInteger.ONE).not();
                BigInteger networkStart = start.and(networkMask);
                BigInteger nextNetworkStart = networkStart.add(blockSize);

                // Check if this block fits within our target range
                if (networkStart.compareTo(start) <= 0 && nextNetworkStart.compareTo(end) <= 0) {
                    break;
                }
                maxPrefix--;
            }

            // Add the valid CIDR block to our list
            String cidr = bigIntegerToIPv6(start) + "/" + maxPrefix;
            cidrList.add(cidr);

            // Move the start address to the end of the current block
            start = start.add(BigInteger.ONE.shiftLeft(128 - maxPrefix));
        }

        return cidrList;
    }

3. Test the Implementation

Add a main method to test with sample IPv6 ranges:

public static void main(String[] args) {
        try {
            // Test case: small contiguous range
            String start = "2001:db8::1";
            String end = "2001:db8::10";
            List<String> cidrs = getCIDRList(start, end);
            System.out.println("CIDR list for range " + start + " to " + end + ":");
            cidrs.forEach(System.out::println);

            // Test case: full /64 subnet range
            start = "2001:db8:1::";
            end = "2001:db8:1::ffff:ffff:ffff:ffff";
            cidrs = getCIDRList(start, end);
            System.out.println("\nCIDR list for range " + start + " to " + end + ":");
            cidrs.forEach(System.out::println);
        } catch (UnknownHostException e) {
            System.err.println("Invalid IPv6 address provided: " + e.getMessage());
        }
    }
}

Key Notes

  • BigInteger Usage: IPv6 addresses are 128 bits long, which is beyond the scope of Java's long (64 bits), so BigInteger is the only viable option for arithmetic operations.
  • Mask Calculation: For a prefix length n, the block size is 2^(128-n). We use bitwise operations to find the network start and ensure it fits within our target range.
  • Automatic Compression: The bigIntegerToIPv6 method uses Inet6Address.getHostAddress(), which automatically compresses consecutive zero segments into ::—so your output CIDR strings will follow standard IPv6 formatting rules.

内容的提问来源于stack exchange,提问作者Rajat Kinkhabwala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:45:50