應用程式伺服器由 Windows 環境整體遷移到 Linux 環境,出現了不能獲取本機 IP 地址的問題。原因是下面一段 JAVA 程式碼在 Linux 下直接返回 127.0.0.1。Windows 下有效的 InetAddress 似乎在 Linux 下不起作用。
public static String getLocalIP() {
String ip = "";
try {
InetAddress address = InetAddress.getLocalHost();
if(address != null) {
ip = address.getHostAddress();
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
return ip;
}
原因在於 Java 使用的 JNI 程式碼調用的是 Linux 中的 gethostname 內核函數。這個函數在 Linux 主機沒有綁定 IP 的情況下根據 Host 檔案定義返回默認的 localhost 或者 127.0.0.1。
後改為改用 NetworkInterface 方式獲取,可以取得 IP 地址。
public static String getLocalIP() {
Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
InetAddress ip = null;
while (allNetInterfaces.hasMoreElements()) {
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
System.out.println(netInterface.getName());
Enumeration addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
ip = (InetAddress) addresses.nextElement();
if (ip != null && ip instanceof Inet4Address) {
return ip.getHostAddress();
}
}
}
}
return "";
}
最後考慮到多塊網卡問題,需要對多個 NetworkInterface 進行遍歷,這裡只取 IPV4 的 IP 地址。
public static List getLocalIPList() {
List ipList = new ArrayList();
try {
Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
NetworkInterface networkInterface;
Enumeration inetAddresses;
InetAddress inetAddress;
String ip;
while (networkInterfaces.hasMoreElements()) {
networkInterface = networkInterfaces.nextElement();
inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
inetAddress = inetAddresses.nextElement();
if (inetAddress != null && inetAddress instanceof Inet4Address) { // IPV4
ip = inetAddress.getHostAddress();
ipList.add(ip);
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return ipList;
}
參考資料:http://www.linuxidc.com/Linux/2012-12/75498.htm https://my.oschina.net/zhongwenhao/blog/307879 http://www.blogjava.net/icewee/archive/2013/07/19/401739.html