一、两种实现方式
package com.lyp;import org.apache.commons.lang3.ObjectUtils;import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;/*** 获取本机IP 地址**/
public class IpUtils {public static void main(String[] args) throws SocketException, UnknownHostException {System.out.println("传统方式-----------hostAddress = " +getTraditionIp());System.out.println( "新方式-----------hostAddress = "+IpUtils.getLocalIp4Address().get().toString().replaceAll("/",""));}/*** 传统方式,非常简单直接通过InetAddress获取,但不准确获取的为虚拟ip* @throws UnknownHostException*/public static String getTraditionIp() throws UnknownHostException {InetAddress localHost = InetAddress.getLocalHost();String hostAddress = localHost.getHostAddress();String hostName = localHost.getHostName();return hostAddress;}/** 获取本机所有网卡信息 得到所有IP信息* @return Inet4Address>*/public static List<Inet4Address> getLocalIp4AddressFromNetworkInterface() throws SocketException {List<Inet4Address> addresses = new ArrayList<>(1);// 所有网络接口信息Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();if (ObjectUtils.isEmpty(networkInterfaces)) {return addresses;}while (networkInterfaces.hasMoreElements()) {NetworkInterface networkInterface = networkInterfaces.nextElement();//滤回环网卡、点对点网卡、非活动网卡、虚拟网卡并要求网卡名字是eth或ens开头if (!isValidInterface(networkInterface)) {continue;}// 所有网络接口的IP地址信息Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();while (inetAddresses.hasMoreElements()) {InetAddress inetAddress = inetAddresses.nextElement();// 判断是否是IPv4,并且内网地址并过滤回环地址.if (isValidAddress(inetAddress)) {addresses.add((Inet4Address) inetAddress);}}}return addresses;}/*** 过滤回环网卡、点对点网卡、非活动网卡、虚拟网卡并要求网卡名字是eth或ens开头** @param ni 网卡* @return 如果满足要求则true,否则false*/private static boolean isValidInterface(NetworkInterface ni) throws SocketException {return !ni.isLoopback() && !ni.isPointToPoint() && ni.isUp() && !ni.isVirtual()&& (ni.getName().startsWith("eth") || ni.getName().startsWith("ens"));}/*** 判断是否是IPv4,并且内网地址并过滤回环地址.*/private static boolean isValidAddress(InetAddress address) {return address instanceof Inet4Address && address.isSiteLocalAddress() && !address.isLoopbackAddress();}/** 通过Socket 唯一确定一个IP* 当有多个网卡的时候,使用这种方式一般都可以得到想要的IP。甚至不要求外网地址8.8.8.8是可连通的* @return Inet4Address>*/private static Optional<Inet4Address> getIpBySocket() throws SocketException {try (final DatagramSocket socket = new DatagramSocket()) {socket.connect(InetAddress.getByName("8.8.8.8"), 10002);if (socket.getLocalAddress() instanceof Inet4Address) {return Optional.of((Inet4Address) socket.getLocalAddress());}} catch (UnknownHostException networkInterfaces) {throw new RuntimeException(networkInterfaces);}return Optional.empty();}/** 获取本地IPv4地址* @return Inet4Address>*/public static Optional<Inet4Address> getLocalIp4Address() throws SocketException {final List<Inet4Address> inet4Addresses = getLocalIp4AddressFromNetworkInterface();if (inet4Addresses.size() != 1) {final Optional<Inet4Address> ipBySocketOpt = getIpBySocket();if (ipBySocketOpt.isPresent()) {return ipBySocketOpt;} else {return inet4Addresses.isEmpty() ? Optional.empty() : Optional.of(inet4Addresses.get(0));}}return Optional.of(inet4Addresses.get(0));}
}
二、测试结果