最近在项目中遇到了一串比较诡异的问题,如下的同一串代码是演示了如何获取本地所有的ip地址:
/**
*
* author:gaoxingliang@outlook.com
* created:2015年8月20日 下午9:16:08
*/
package blog;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
/**
* @author gxl
*
*/
public class GetLocalIps
{
public static void main(String[] args) throws SocketException
{
//get all local ips
Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
while (interfs.hasMoreElements())
{
NetworkInterface interf = interfs.nextElement();
Enumeration<InetAddress> addres = interf.getInetAddresses();
while (addres.hasMoreElements())
{
InetAddress in = addres.nextElement();
if (in instanceof Inet4Address)
{
System.out.println("v4:" + in.getHostAddress());
}
else if (in instanceof Inet6Address)
{
System.out.println("v6:" + in.getHostAddress());
}
}
}
}
}
上面的代码在本地环境返回了所有的ip 包括IPV6:
v4:127.0.0.1
v6:0:0:0:0:0:0:0:1
v4:169.254.177.100
v6:fe80:0:0:0:b0f5:493b:f105:b164%eth1
v4:192.168.0.100
v6:fe80:0:0:0:d48a:e3be:7d9d:899c%eth2
但是在运行环境上却只返回了如下的地址:
v4:127.0.0.1
v4:169.254.177.100
v4:192.168.0.100
发现少了IPV6,纳闷了好久,没办就看下java的实现,然后跟踪到如下代码:java.net.NetworkInterface.getNetworkInterfaces()
public static Enumeration<NetworkInterface> getNetworkInterfaces()
throws SocketException {
final NetworkInterface[] netifs = getAll();
java的实现:
private native static NetworkInterface[] getAll()
throws SocketException;
是一个native的方法,于是参考了jdk源码,发现果然是java 运行参数导致的.
jdk源码:
openjdk\jdk\src\solaris\native\java\net\NetworkInterface.c
/*
* Enumerates all interfaces
*/
static netif *enumInterfaces(JNIEnv *env) {
netif *ifs;
int sock;
/*
* Enumerate IPv4 addresses
*/
sock = openSocket(env, AF_INET);
if (sock < 0 && (*env)->ExceptionOccurred(env)) {
return NULL;
}
ifs = enumIPv4Interfaces(env, sock, NULL);
close(sock);
if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
return NULL;
}
/* return partial list if exception occure in the middle of process ???*/
/*
* If IPv6 is available then enumerate IPv6 addresses.
*/
#ifdef AF_INET6
/* User can disable ipv6 expicitly by -Djava.net.preferIPv4Stack=true,
* so we have to call ipv6_available()
*/
if (ipv6_available()) {
sock = openSocket(env, AF_INET6);
if (sock < 0 && (*env)->ExceptionOccurred(env)) {
freeif(ifs);
return NULL;
}
ifs = enumIPv6Interfaces(env, sock, ifs);
close(sock);
if ((*env)->ExceptionOccurred(env)) {
freeif(ifs);
return NULL;
}
}
#endif
return ifs;
}
有-Djava.net.preferIPv4Stack=true 参数后便不会有IPV6的地址.
jdk源码:
http://pan.baidu.com/s/1jGvmnrw