326 lines
9.4 KiB
Java
326 lines
9.4 KiB
Java
package org.kne.cloud.network;
|
||
|
||
import java.net.Inet6Address;
|
||
import java.net.InetSocketAddress;
|
||
import java.net.SocketAddress;
|
||
import java.net.UnknownHostException;
|
||
import java.nio.ByteBuffer;
|
||
|
||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||
|
||
/**
|
||
* 高性能IPv6套接字地址实现,替代Java原生的InetSocketAddress
|
||
* 大幅减少GC压力和提高网络栈性能
|
||
*/
|
||
public final class IPv6SocketAddress {
|
||
|
||
|
||
private static final long serialVersionUID = 1L;
|
||
|
||
private final IPv6Address address;
|
||
private final int port;
|
||
|
||
// 常用常量
|
||
public static final IPv6SocketAddress ANY = new IPv6SocketAddress(IPv6Address.UNSPECIFIED, 0);
|
||
|
||
// 构造方法
|
||
public IPv6SocketAddress(IPv6Address address, int port ) {
|
||
if (address == null) {
|
||
throw new IllegalArgumentException("Address cannot be null");
|
||
}
|
||
if (port < 0 || port > 65535) {
|
||
throw new IllegalArgumentException("Port out of range: " + port);
|
||
}
|
||
this.address = address;
|
||
this.port = port;
|
||
}
|
||
|
||
/**
|
||
* 从IPv6地址和端口创建
|
||
*/
|
||
public static IPv6SocketAddress valueOf(IPv6Address address, int port) {
|
||
return new IPv6SocketAddress(address, port);
|
||
}
|
||
|
||
/**
|
||
* 从两个long和端口创建(最高性能)
|
||
*/
|
||
public static IPv6SocketAddress valueOf(long high, long low, int port) {
|
||
return new IPv6SocketAddress(IPv6Address.valueOf(high, low), port);
|
||
}
|
||
|
||
/**
|
||
* 从byte[16]和端口创建
|
||
*/
|
||
public static IPv6SocketAddress valueOf(byte[] addressBytes, int port) {
|
||
return new IPv6SocketAddress(IPv6Address.valueOf(addressBytes), port);
|
||
}
|
||
|
||
/**
|
||
* 从ByteBuffer创建(零拷贝友好)
|
||
*/
|
||
public static IPv6SocketAddress valueOf(ByteBuffer buffer) {
|
||
if (buffer.remaining() < 18) { // 16字节地址 + 2字节端口
|
||
throw new IllegalArgumentException("Buffer must have at least 18 bytes remaining");
|
||
}
|
||
|
||
long high = buffer.getLong();
|
||
long low = buffer.getLong();
|
||
int port = buffer.getShort() & 0xFFFF;
|
||
|
||
return valueOf(high, low, port);
|
||
}
|
||
|
||
/**
|
||
* 从ByteBuffer指定位置创建
|
||
*/
|
||
public static IPv6SocketAddress valueOf(int offset, ByteBuffer buffer) {
|
||
if (buffer.remaining() < offset + 18) {
|
||
throw new IllegalArgumentException("Buffer too small");
|
||
}
|
||
|
||
long high = buffer.getLong(offset);
|
||
long low = buffer.getLong(offset + 8);
|
||
int port = buffer.getShort(offset + 16) & 0xFFFF;
|
||
|
||
return valueOf(high, low, port);
|
||
}
|
||
|
||
/**
|
||
* 从Java InetSocketAddress转换
|
||
*/
|
||
public static IPv6SocketAddress valueOf(InetSocketAddress inetSocketAddress) {
|
||
if (inetSocketAddress == null) {
|
||
throw new IllegalArgumentException("InetSocketAddress cannot be null");
|
||
}
|
||
|
||
IPv6Address addr = IPv6Address.valueOf(inetSocketAddress.getAddress());
|
||
int port = inetSocketAddress.getPort();
|
||
|
||
return new IPv6SocketAddress(addr, port);
|
||
}
|
||
|
||
/**
|
||
* 从字符串解析(格式: [ipv6]:port 或 ipv6:port)
|
||
*/
|
||
public static IPv6SocketAddress valueOf(String socketAddress) {
|
||
if (socketAddress == null || socketAddress.isEmpty()) {
|
||
throw new IllegalArgumentException("Invalid socket address string");
|
||
}
|
||
|
||
try {
|
||
// 处理[ipv6]:port格式
|
||
if (socketAddress.startsWith("[")) {
|
||
int closeBracket = socketAddress.indexOf(']');
|
||
if (closeBracket == -1) {
|
||
throw new IllegalArgumentException("Invalid IPv6 socket address format");
|
||
}
|
||
|
||
String ipPart = socketAddress.substring(1, closeBracket);
|
||
String portPart = socketAddress.substring(closeBracket + 1);
|
||
|
||
if (!portPart.startsWith(":")) {
|
||
throw new IllegalArgumentException("Invalid IPv6 socket address format");
|
||
}
|
||
|
||
IPv6Address address = IPv6Address.valueOf(ipPart);
|
||
int port = Integer.parseInt(portPart.substring(1));
|
||
|
||
return valueOf(address, port);
|
||
} else {
|
||
// 处理ipv6:port格式(简单情况)
|
||
int lastColon = socketAddress.lastIndexOf(':');
|
||
if (lastColon == -1) {
|
||
throw new IllegalArgumentException("Invalid IPv6 socket address format");
|
||
}
|
||
|
||
String ipPart = socketAddress.substring(0, lastColon);
|
||
String portPart = socketAddress.substring(lastColon + 1);
|
||
|
||
IPv6Address address = IPv6Address.valueOf(ipPart);
|
||
int port = Integer.parseInt(portPart);
|
||
|
||
return valueOf(address, port);
|
||
}
|
||
} catch (Exception e) {
|
||
throw new IllegalArgumentException("Invalid IPv6 socket address: " + socketAddress, e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建未解析的地址(带hostname)
|
||
* @throws UnknownHostException
|
||
*/
|
||
public static IPv6SocketAddress createUnresolved(String hostname, int port) throws UnknownHostException {
|
||
if (hostname == null || hostname.isEmpty()) {
|
||
throw new IllegalArgumentException("Hostname cannot be null or empty");
|
||
}
|
||
if (port < 0 || port > 65535) {
|
||
throw new IllegalArgumentException("Port out of range: " + port);
|
||
}
|
||
|
||
return new IPv6SocketAddress(IPv6Address.valueOf ( hostname), port);
|
||
}
|
||
|
||
// 核心getter方法
|
||
public IPv6Address getAddress() {
|
||
return address;
|
||
}
|
||
|
||
public int getPort() {
|
||
return port;
|
||
}
|
||
|
||
/**
|
||
* 转换为byte数组(18字节:16字节地址 + 2字节端口)
|
||
*/
|
||
public byte[] toByteArray() {
|
||
byte[] bytes = new byte[18];
|
||
toByteArray(bytes, 0);
|
||
return bytes;
|
||
}
|
||
|
||
/**
|
||
* 写入到现有byte数组
|
||
*/
|
||
public void toByteArray(byte[] dest, int offset) {
|
||
if (dest.length - offset < 18) {
|
||
throw new IllegalArgumentException("Destination array too small");
|
||
}
|
||
|
||
address.toByteArray(dest, offset);
|
||
dest[offset + 16] = (byte) (port >> 8);
|
||
dest[offset + 17] = (byte) port;
|
||
}
|
||
|
||
/**
|
||
* 写入到ByteBuffer(高性能网络操作)
|
||
*/
|
||
public void writeTo(ByteBuffer buffer) {
|
||
address.writeTo(buffer);
|
||
buffer.putShort((short) port);
|
||
}
|
||
|
||
/**
|
||
* 写入到ByteBuffer指定位置
|
||
*/
|
||
public void writeTo(int offset, ByteBuffer buffer) {
|
||
address.writeTo(offset, buffer);
|
||
buffer.putShort(offset + 16, (short) port);
|
||
}
|
||
|
||
/**
|
||
* 转换为Java InetSocketAddress(兼容性方法)
|
||
*/
|
||
public InetSocketAddress toInetSocketAddress() {
|
||
Inet6Address inet6Addr = address.toInet6Address();
|
||
return new InetSocketAddress(inet6Addr, port);
|
||
}
|
||
|
||
// 实用方法
|
||
|
||
/**
|
||
* 检查是否为通配符地址(0.0.0.0:0)
|
||
*/
|
||
public boolean isWildcardAddress() {
|
||
return address.equals(IPv6Address.UNSPECIFIED) && port == 0;
|
||
}
|
||
|
||
/**
|
||
* 检查是否为环回地址
|
||
*/
|
||
public boolean isLoopbackAddress() {
|
||
return address.isLoopbackAddress();
|
||
}
|
||
|
||
/**
|
||
* 检查是否为多播地址
|
||
*/
|
||
public boolean isMulticastAddress() {
|
||
return address.isMulticastAddress();
|
||
}
|
||
|
||
/**
|
||
* 检查是否为链路本地地址
|
||
*/
|
||
public boolean isLinkLocalAddress() {
|
||
return address.isLinkLocalAddress();
|
||
}
|
||
|
||
/**
|
||
* 检查是否为站点本地地址
|
||
*/
|
||
public boolean isSiteLocalAddress() {
|
||
return address.isSiteLocalAddress();
|
||
}
|
||
|
||
/**
|
||
* 获取多播地址的scope
|
||
*/
|
||
public int getMulticastScope() {
|
||
return address.getMulticastScope();
|
||
}
|
||
|
||
// 路由相关的实用方法
|
||
|
||
/**
|
||
* 检查地址是否在指定网络内
|
||
*/
|
||
public boolean isInNetwork(IPv6Address network, int prefixLength) {
|
||
return address.isInNetwork(network, prefixLength);
|
||
}
|
||
|
||
/**
|
||
* 应用网络掩码
|
||
*/
|
||
public IPv6SocketAddress maskWith(IPv6Address mask) {
|
||
return valueOf(address.maskWith(mask), port);
|
||
}
|
||
|
||
// 比较和哈希
|
||
|
||
|
||
@Override
|
||
public int hashCode() {
|
||
final int prime = 31;
|
||
int result = 1;
|
||
result = prime * result + ((address == null) ? 0 : address.hashCode());
|
||
result = prime * result + port;
|
||
return result;
|
||
}
|
||
|
||
@Override
|
||
public boolean equals(Object obj) {
|
||
if (this == obj)
|
||
return true;
|
||
if (obj == null)
|
||
return false;
|
||
if (getClass() != obj.getClass())
|
||
return false;
|
||
IPv6SocketAddress other = (IPv6SocketAddress) obj;
|
||
if (address == null) {
|
||
if (other.address != null)
|
||
return false;
|
||
} else if (!address.equals(other.address))
|
||
return false;
|
||
if (port != other.port)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
|
||
@Override
|
||
public String toString() {
|
||
// 对于IPv6地址,使用方括号括起来
|
||
return "[" + address.toString() + "]:" + port;
|
||
}
|
||
|
||
/**
|
||
* 转换为压缩形式的字符串
|
||
*/
|
||
public String toCompressedString() {
|
||
return "[" + address.toCompressedString() + "]:" + port;
|
||
}
|
||
|
||
|
||
} |