使用 Java 开发兼容 IPv6 的网络应用程序
2010-06-08 00:00:00 来源:WEB开发网如何正规化 IPv6 地址
在网络程序开发中,经常使用 IP 地址来标识一个主机,例如记录终端用户的访问记录等。由于 IPv6 具有有零压缩地址等多种表示形式,因此直接使用 IPv6 地址作为标示符,可能会带来一些问题。为了避免这些问题,在使用 IPv6 地址之前,有必要将其正规化。除了通过我们熟知的正则表达式,笔者在开发过程中发现使用一个简单的 Java API 也可以达到相同的效果。
清单 2. 正规化地址
InetAddress inetAddr = InetAddress.getByName(ipAddr);
ipAddr = inetAddr.getHostAddress();
System.out.println(ipAddr);
InetAddress.getByName(String) 方法接受的参数既可以是一个主机名,也可以是一个 IP 地址字符串。我们输入任一信息的合法 IPv6 地址,再通过 getHostAddress() 方法取出主机 IP 时,地址字符串 ipAddr 已经被转换为完整形式。例如输入 2002:97b:e7aa::97b:e7aa,上述代码执行过后,零压缩部分将被还原,ipAddr 变为 2002:97b:e7aa:0:0:0:97b:e7aa。
如何获取本机 IPv6 地址
有时为了能够注册 listener,开发人员需要使用本机的 IPv6 地址,这一地址不能简单得通过 InetAddress.getLocalhost() 获得。因为这样有可能获得诸如 0:0:0:0:0:0:0:1 这样的特殊地址。使用这样的地址,其他服务器将无法把通知发送到本机上,因此必须先进行过滤,选出确实可用的地址。以下代码实现了这一功能,思路是遍历网络接口的各个地址,直至找到符合要求的地址。
清单 3. 获取本机 IP 地址
public static String getLocalIPv6Address() throws IOException {
InetAddress inetAddress = null;
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
.getNetworkInterfaces();
outer:
while (networkInterfaces.hasMoreElements()) {
Enumeration<InetAddress> inetAds = networkInterfaces.nextElement()
.getInetAddresses();
while (inetAds.hasMoreElements()) {
inetAddress = inetAds.nextElement();
//Check if it's ipv6 address and reserved address
if (inetAddress instanceof Inet6Address
&& !isReservedAddr(inetAddress)) {
break outer;
}
}
}
String ipAddr = inetAddress.getHostAddress();
// Filter network card No
int index = ipAddr.indexOf('%');
if (index > 0) {
ipAddr = ipAddr.substring(0, index);
}
return ipAddr;
}
/**
* Check if it's "local address" or "link local address" or
* "loopbackaddress"
*
* @param ip address
*
* @return result
*/
private static boolean isReservedAddr(InetAddress inetAddr) {
if (inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress()
|| inetAddr.isLoopbackAddress()) {
return true;
}
return false;
}
更多精彩
赞助商链接