一、什么是IPV6
IPv6 是互联网的“新版地址系统”,就像给每台设备(手机、电脑、冰箱、灯泡、智能家电等)发一个超长的唯一“门牌号”,确保未来所有智能设备都能轻松连上网。
二、为什么需要IPV6
原来的IPv4地址(比如 192.168.1.1)总共有约43亿个,但全球设备早就超过这个数量,根本不够用了。IPv6的地址数量多到几乎无限(约340万亿亿亿亿个),可以给地球上每粒沙子都分配一个地址!
三、IPv6长什么样?
它看起来像这样:
2001:0db8:85a3:0000:0000:8a2e:0370:7334,用冒号分隔的8组数字+字母(比如 abcd:1234::)组成,比IPv4复杂得多。
四、IPv6有什么好处?
- 再也不怕地址不够用
- 联网更简单(设备能自动配置地址)
- 安全性更好(内置加密功能)
五、IPV6中PD和ND
- PD(Prefix Delegation,前缀分配)
比喻:好比房东(运营商)给你(路由器)分配一个超大的地址段(比如 2409:876A::/48),相当于给了你一栋楼的所有房间号。你可以自己把这些房间号分给租客(家里的手机、电脑、智能设备)。
用途:让路由器自动从运营商拿到一大块IPv6地址,再分配给家里的设备,无需手动设置。
- ND(Neighbor Discovery,邻居发现)
比喻:像小区里的“门卫系统”。当你的手机(IPv6设备)想给隔壁的电脑发消息时,ND 协议会自动喊一嗓子:“电脑的地址是哪个?”,电脑就会回应:“我在这儿!我的地址是xxxx”。
用途:自动发现同一网络内的其他设备(类似IPv4的ARP协议),还能让设备自动配置地址。
- 总结:
- PD:运营商给路由器“批发地址”,路由器再“零售”给设备。
- ND:设备之间的“对讲机”,帮你找到邻居并通信。
六、已知IPV6地址段和PD前缀如何计算地址段总数以及随机生成每个地址段一个可用的IP地址
- 例如:已知 IPV6地址段: 2409:876a:00b0::/44 , PD前缀是 60, 能分多少个子网段?,随机生成几个子网段的具体ip地址
- 代码示例:
import
inet.ipaddr.AddressStringException; import inet.ipaddr.IPAddress; import
inet.ipaddr.IPAddressString; import
inet.ipaddr.ipv6.IPv6Address; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * IPv6地址生成工具类 * 用于生成指定范围内的随机IPv6地址 */ public class IPAddressExample { private static final Logger log = LoggerFactory.getLogger(IPAddressExample.class); private static final int INTERFACE_ID_MAX = 65536; private static final int SEGMENTS_LENGTH = 8; private static final Random RANDOM = new Random(); /** * 生成指定数量的随机IPv6子网地址 * * @param ipRange IPv6地址范围,格式如 "2409:876a:00b0::/44" * @param pdPrefix 委派前缀长度 * @param count 需要生成的地址数量 * @return 生成的IPv6地址列表 * @throws AddressStringException 当IPv6地址格式不正确时抛出异常 */ public static List
generateRandomSubnetAddresses(String ipRange, int pdPrefix, int count) throws AddressStringException { List
network.getNetworkPrefixLength(); long totalSubnets = 1L << (pdPrefix - originalPrefix); log.info("原始前缀长度: /{}, PD前缀长度: /{}, 可用子网段数量: {}", originalPrefix, pdPrefix, totalSubnets); for (int i = 0; i < count; i++) { String address = generateRandomAddress((IPv6Address) network, originalPrefix, pdPrefix, totalSubnets); generatedAddresses.add(address); log.info("子网段 {} 示例IP地址: {}", (i + 1), address); } return generatedAddresses; } /** * 生成单个随机IPv6地址 * * @param baseAddress 基础IPv6地址 * @param originalPrefix 原始前缀长度 * @param pdPrefix 委派前缀长度 * @param totalSubnets 可用子网总数 * @return 生成的IPv6地址字符串 */ private static String generateRandomAddress(IPv6Address baseAddress, int originalPrefix, int pdPrefix, long totalSubnets) { long randomSubnetIndex = Math.abs(RANDOM.nextLong()) % totalSubnets; int[] segments = initializeSegments(baseAddress); applySubnetIndex(segments, randomSubnetIndex, originalPrefix, pdPrefix); generateInterfaceId(segments); return buildIPv6Address(segments); } /** * 初始化IPv6地址段数组 * * @param baseAddress 基础IPv6地址 * @return 初始化后的地址段数组 */ private static int[] initializeSegments(IPv6Address baseAddress) { int[] segments = new int[SEGMENTS_LENGTH]; for (int j = 0; j < segments_length j segmentsj='baseAddress.getSegment(j).getValue().intValue();' return segments param segments ipv6 param randomsubnetindex param originalprefix param pdprefix private static void applysubnetindexint segments long randomsubnetindex int originalprefix int pdprefix int startsegmentindex='originalPrefix' 16 int bitoffset='originalPrefix' 16 if bitoffset> 0) { segments[startSegmentIndex] |= (randomSubnetIndex >>> (pdPrefix - originalPrefix - 16 + bitOffset)) & 0xFFFF; } if (startSegmentIndex + 1 < 4) { segments[startSegmentIndex + 1] = (int)((randomSubnetIndex << (32 - (pdPrefix - originalPrefix))) & 0xFFFF); } } /** * 生成接口标识符(Interface ID) * 随机生成IPv6地址的后64位 * * @param segments IPv6地址段数组 */ private static void generateInterfaceId(int[] segments) { for (int i = 4; i < SEGMENTS_LENGTH; i++) { segments[i] = RANDOM.nextInt(INTERFACE_ID_MAX); } } /** * 将地址段数组转换为IPv6地址字符串 * * @param segments IPv6地址段数组 * @return 格式化的IPv6地址字符串 */ private static String buildIPv6Address(int[] segments) { StringBuilder ipBuilder = new StringBuilder(); for (int j = 0; j < segments.length j if j> 0) { ipBuilder.append(':'); } ipBuilder.append(String.format("%x", segments[j])); } return ipBuilder.toString(); } /** * 主方法,用于测试IPv6地址生成 * * @param args 命令行参数(未使用) * @throws AddressStringException 当IPv6地址格式不正确时抛出异常 */ public static void main(String[] args) throws AddressStringException { String ipRange = "2409:876a:00b0::/44"; int pdPrefix = 60; int count = 5;
generateRandomSubnetAddresses(ipRange, pdPrefix, count); } }
七、根据分配的IPV6地址、IPV6地址段和地址前缀计算出已使用的地址段数
只要这个IPV6地址属于某一个段就算这个地址段已使用,也就是已使用地址数
代码示例:
import
inet.ipaddr.AddressStringException; import inet.ipaddr.IPAddress; import
inet.ipaddr.IPAddressString; import java.util.HashSet; import java.util.Set; /** * 根据分配的IPV6地址、IPV6地址段和地址前缀计算出已使用的地址段数 */ public class CalUsedIpRangeUtil { public static void main(String[] args) throws AddressStringException { // 定义要检查的IP地址段 数据库查询出来的地址段 String ipRange = "2409:876a:00b0::/44"; // 已分配的IPV6地址列表 根据地址段查询出对应分配的具体IP地址列表 String[] assignedIpAddresses = { "
2409:876a:b0:0004:0000:0000:0000:0001", "
2409:876a:b0:1234:8a72:5b31:9c45:def1", "
2409:876a:b0:5678:1234:abcd:ef01:2345", "
2409:876a:b0:9abc:def0:1234:5678:9abc", "
2409:876a:b0:def0:4321:8765:abcd:ef01", "
2409:876a:b0:4567:89ab:cdef:0123:4567" }; int usedSubnetCount = countUsedSubnets(ipRange, assignedIpAddresses, 60); System.out.println("已使用的/60子网段数量: " + usedSubnetCount); } private static int countUsedSubnets(String ipRange, String[] assignedIpAddresses, int prefix) throws AddressStringException { // 创建一个Set来存储不同的子网段 Set