package org.kne.cloud.network.ipv6; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; import org.kne.cloud.network.klalb.KLALBUtils; /** * 高性能IPv6地址实现,使用两个long代替byte[16], * 大幅减少GC压力和提高路由表查找性能 */ public final class IPv6Address implements Comparable { private final long high; private final long low; // 常用常量地址 public static final IPv6Address LOOPBACK = new IPv6Address(0, 1); public static final IPv6Address UNSPECIFIED = new IPv6Address(0, 0); public static final IPv6Address LOCALHOST = LOOPBACK; // IPv4映射的IPv6地址前缀 private static final long IPV4_MAPPED_HIGH = 0x0000_0000_0000_0000L; private static final long IPV4_MAPPED_LOW_PREFIX = 0x0000_0000_FFFF_0000L; // 构造方法 public IPv6Address(long high, long low) { this.high = high; this.low = low; } public IPv6Address(Inet6Address address) { this(address.getAddress()); } public IPv6Address(byte[] bytes) { if (bytes.length != 16) { throw new IllegalArgumentException("IPv6 address must be 16 bytes"); } this. high = ((long)(bytes[0] & 0xFF) << 56) | ((long)(bytes[1] & 0xFF) << 48) | ((long)(bytes[2] & 0xFF) << 40) | ((long)(bytes[3] & 0xFF) << 32) | ((long)(bytes[4] & 0xFF) << 24) | ((long)(bytes[5] & 0xFF) << 16) | ((long)(bytes[6] & 0xFF) << 8) | ((long)(bytes[7] & 0xFF)); this.low = ((long)(bytes[8] & 0xFF) << 56) | ((long)(bytes[9] & 0xFF) << 48) | ((long)(bytes[10] & 0xFF) << 40) | ((long)(bytes[11] & 0xFF) << 32) | ((long)(bytes[12] & 0xFF) << 24) | ((long)(bytes[13] & 0xFF) << 16) | ((long)(bytes[14] & 0xFF) << 8) | ((long)(bytes[15] & 0xFF)); } /** * 从两个long创建IPv6地址 */ public static IPv6Address valueOf(long high, long low) { return new IPv6Address(high, low); } /** * 从byte[16]创建IPv6地址(高性能版本) */ public static IPv6Address valueOf(byte[] bytes) { return new IPv6Address(bytes); } /** * 从ByteBuffer创建IPv6地址(零拷贝友好) */ public static IPv6Address valueOf(ByteBuffer buffer) { if (buffer.remaining() < 16) { throw new IllegalArgumentException("Buffer must have at least 16 bytes remaining"); } long high = buffer.getLong(); long low = buffer.getLong(); return valueOf(high, low); } public static IPv6Address valueOf(int offset, ByteBuffer buffer) { long high = buffer.getLong(offset); long low = buffer.getLong(offset+8); return valueOf(high, low); } /** * 从字符串解析IPv6地址(高性能版本) * @throws UnknownHostException */ public static IPv6Address valueOf(String ipString) throws UnknownHostException { if (ipString == null || ipString.isEmpty()) { throw new IllegalArgumentException("Invalid IPv6 address string"); } return new IPv6Address((Inet6Address)Inet6Address.getByName(ipString)); } /** * 从Java InetAddress转换 */ public static IPv6Address valueOf(InetAddress inetAddress) { if (inetAddress == null) { throw new IllegalArgumentException("InetAddress cannot be null"); } byte[] bytes = inetAddress.getAddress(); if (bytes.length == 4) { // IPv4地址,转换为IPv4映射的IPv6地址 return valueOf(IPV4_MAPPED_HIGH, IPV4_MAPPED_LOW_PREFIX | (((long)(bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF))); } return valueOf(bytes); } // 核心getter方法 public long getHigh() { return high; } public long getLow() { return low; } /** * 转换为byte[16](需要时使用) */ public byte[] toByteArray() { byte[] bytes = new byte[16]; toByteArray(bytes, 0); return bytes; } /** * 写入到现有byte数组(避免创建新对象) */ public void toByteArray(byte[] dest, int offset) { if (dest.length - offset < 16) { throw new IllegalArgumentException("Destination array too small"); } dest[offset] = (byte) (high >> 56); dest[offset + 1] = (byte) (high >> 48); dest[offset + 2] = (byte) (high >> 40); dest[offset + 3] = (byte) (high >> 32); dest[offset + 4] = (byte) (high >> 24); dest[offset + 5] = (byte) (high >> 16); dest[offset + 6] = (byte) (high >> 8); dest[offset + 7] = (byte) high; dest[offset + 8] = (byte) (low >> 56); dest[offset + 9] = (byte) (low >> 48); dest[offset + 10] = (byte) (low >> 40); dest[offset + 11] = (byte) (low >> 32); dest[offset + 12] = (byte) (low >> 24); dest[offset + 13] = (byte) (low >> 16); dest[offset + 14] = (byte) (low >> 8); dest[offset + 15] = (byte) low; } /** * 写入到ByteBuffer(高性能网络操作) */ public void writeTo(ByteBuffer buffer) { buffer.putLong(high); buffer.putLong(low); } public void writeTo(int offset, ByteBuffer buffer) { buffer.putLong(offset,high); buffer.putLong(offset+8,low); } /** * 转换为标准IPv6字符串表示 */ @Override public String toString() { try { return Inet6Address.getByAddress(toByteArray()).getHostAddress(); } catch (UnknownHostException e) { return "Internal Error"; } } /** * 转换为压缩形式的字符串(::格式) */ public String toCompressedString() { return KLALBUtils.parseAbbrIPv6(toString()); } /** * 检查是否为IPv4映射地址 */ public boolean isIPv4MappedAddress() { return high == IPV4_MAPPED_HIGH && (low & 0x0000_0000_FFFF_0000L) == IPV4_MAPPED_LOW_PREFIX; } /** * 如果这是IPv4映射地址,提取IPv4部分 */ public byte[] getIPv4Bytes() { if (!isIPv4MappedAddress()) { throw new IllegalStateException("Not an IPv4 mapped address"); } byte[] ipv4 = new byte[4]; ipv4[0] = (byte) (low >> 24); ipv4[1] = (byte) (low >> 16); ipv4[2] = (byte) (low >> 8); ipv4[3] = (byte) low; return ipv4; } /** * 检查是否为多播地址 */ public boolean isMulticastAddress() { return (high & 0xFF00_0000_0000_0000L) == 0xFF00_0000_0000_0000L; } /** * 检查是否为链路本地地址 */ public boolean isLinkLocalAddress() { return (high & 0xFFC0_0000_0000_0000L) == 0xFE80_0000_0000_0000L; } /** * 检查是否为站点本地地址(已弃用,但为了兼容性保留) */ public boolean isSiteLocalAddress() { return (high & 0xFFC0_0000_0000_0000L) == 0xFEC0_0000_0000_0000L; } /** * 检查是否为唯一本地地址 (ULA) */ public boolean isUniqueLocalAddress() { return (high & 0xFE00_0000_0000_0000L) == 0xFC00_0000_0000_0000L; } /** * 检查是否为环回地址 */ public boolean isLoopbackAddress() { return this.equals(LOOPBACK); } /** * 检查是否为未指定地址 */ public boolean isUnspecifiedAddress() { return this.equals(UNSPECIFIED); } /** * 获取多播地址的scope */ public int getMulticastScope() { if (!isMulticastAddress()) { return -1; } return (int) ((low >> 48) & 0x0F); } // 路由表相关的实用方法 /** * 创建掩码(用于CIDR表示法) */ public static IPv6Address createMask(int prefixLength) { if (prefixLength < 0 || prefixLength > 128) { throw new IllegalArgumentException("Prefix length must be between 0 and 128"); } long maskHigh, maskLow; if (prefixLength == 128) { maskHigh = -1L; // 0xFFFFFFFF_FFFFFFFF maskLow = -1L; } else if (prefixLength > 64) { maskHigh = -1L; maskLow = (-1L) << (64 - (prefixLength - 64)); } else if (prefixLength == 64) { maskHigh = -1L; maskLow = 0; } else { maskHigh = (-1L) << (64 - prefixLength); maskLow = 0; } return valueOf(maskHigh, maskLow); } /** * 应用掩码(用于网络地址计算) */ public IPv6Address maskWith(IPv6Address mask) { return valueOf(high & mask.high, low & mask.low); } /** * 检查地址是否在指定网络内 */ public boolean isInNetwork(IPv6Address network, IPv6Address mask) { IPv6Address maskedThis = this.maskWith(mask); IPv6Address maskedNetwork = network.maskWith(mask); return maskedThis.equals(maskedNetwork); } /** * 检查地址是否在指定CIDR网络内 */ public boolean isInNetwork(IPv6Address network, int prefixLength) { IPv6Address mask = createMask(prefixLength); return isInNetwork(network, mask); } // 比较和哈希 @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; IPv6Address other = (IPv6Address) obj; return high == other.high && low == other.low; } @Override public int hashCode() { // 优化的哈希计算,考虑long的分布 return (int) (high ^ (high >>> 32) ^ low ^ (low >>> 32)); } @Override public int compareTo(IPv6Address other) { int highCompare = Long.compareUnsigned(high, other.high); if (highCompare != 0) return highCompare; return Long.compareUnsigned(low, other.low); } public static void main(String[] args) throws UnknownHostException { // 创建IPv6地址 IPv6Address addr1 = IPv6Address.valueOf("2001:db8::1"); IPv6Address addr2 = IPv6Address.valueOf(0x20010DB800000000L, 0x0000000000000001L); // 高性能路由表查找 IPv6Address target = IPv6Address.valueOf("2001:db8:1234::5678"); IPv6Address network = IPv6Address.valueOf("2001:db8:1234::"); int prefixLength = 64; if (target.isInNetwork(network, prefixLength)) { System.out.println("地址在目标网络内"); } // 转换为字节数组(需要时) byte[] bytes = addr1.toByteArray(); // 直接写入ByteBuffer(零拷贝) ByteBuffer buffer = ByteBuffer.allocateDirect(16); addr1.writeTo(buffer); } public Inet6Address toInet6Address() { try { return (Inet6Address) Inet6Address.getByAddress(toByteArray()); } catch (UnknownHostException e) { return null; } } public boolean isAnyLocalAddress() { return high==0&&low==0; } }