获取本地内网 IP 地址的方法
Java 获取本地内网 IP 地址的方法。
获取本地内网 IP 地址的方法
获取第一个内网 IP
行为特征:
- 遍历网络接口,返回第一个符合条件的内网 IP
- 顺序依赖于系统网络接口的枚举顺序
- 不保证返回的是 "最佳"IP
适用场景: 只需要一个可用的内网 IP,对具体是哪个网段不敏感
/**
* 获取本地内网IP地址
* @return 本地内网IP地址
*/
public static String getLocalIntranetIp() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
// 跳过回环接口和非激活接口
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
// 只处理IPv4地址且非回环地址
if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
String ip = inetAddress.getHostAddress();
// 判断是否为内网IP
if (isInnerIP(ip)) {
return ip;
}
}
}
}
} catch (Exception e) {
log.error("获取本地内网IP失败", e);
}
return "127.0.0.1";
}
获取所有内网 IP
行为特征:
- 遍历所有网络接口,收集所有内网 IP
- 包含多网卡、虚拟网卡、VPN 等产生的 IP
- 提供完整的网络环境视图
适用场景: 需要了解完整网络环境,或让用户选择特定网卡
/**
* 获取所有本地内网IP地址
* @return 本地内网IP地址列表
*/
public static List<String> getAllLocalIntranetIps() {
List<String> ipList = new ArrayList<>();
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
// 跳过回环接口和非激活接口
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
// 只处理IPv4地址且非回环地址
if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
String ip = inetAddress.getHostAddress();
// 判断是否为内网IP
if (isInnerIP(ip)) {
ipList.add(ip);
}
}
}
}
} catch (Exception e) {
log.error("获取所有本地内网IP失败", e);
}
return ipList;
}
获取首选内网 IP
行为特征:
- 智能选择最适合的 IP 地址
- 优先选择家庭 / 办公室常用的 192.168 网段
- 避免返回 Docker、VM 等虚拟网络的 IP
适用场景: 需要一个 "最佳" 的本地 IP,用于服务绑定、日志记录等
/**
* 获取首选的本地内网IP(优先级:192.168.x.x > 10.x.x.x > 172.16-31.x.x)
* @return 首选的本地内网IP地址
*/
public static String getPreferredLocalIntranetIp() {
List<String> ipList = getAllLocalIntranetIps();
if (ipList.isEmpty()) {
return "127.0.0.1";
}
// 优先返回192.168网段的IP
for (String ip : ipList) {
if (ip.startsWith("192.168.")) {
return ip;
}
}
// 其次返回10网段的IP
for (String ip : ipList) {
if (ip.startsWith("10.")) {
return ip;
}
}
// 最后返回172.16-31网段的IP
for (String ip : ipList) {
if (ip.startsWith("172.")) {
String[] parts = ip.split("\\.");
if (parts.length >= 2) {
int secondOctet = Integer.parseInt(parts[1]);
if (secondOctet >= 16 && secondOctet <= 31) {
return ip;
}
}
}
}
// 如果都没有,返回第一个
return ipList.get(0);
}
其他补充方法
/**
* 获取本地主机名
* @return 本地主机名
*/
public static String getLocalHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
log.error("获取本地主机名失败", e);
return "unknown";
}
}
/**
* 获取本地IP和主机名信息
* @return 格式为 "IP(hostname)" 的字符串
*/
public static String getLocalIpWithHostName() {
String ip = getPreferredLocalIntranetIp();
String hostname = getLocalHostName();
return ip + "(" + hostname + ")";
}
完整的导入语句
在文件顶部添加这些导入:
import java.net.NetworkInterface;
import java.net.Inet4Address;
import java.util.Enumeration;
import java.util.ArrayList;
使用示例
public static void main(String[] args) {
// 获取单个内网IP
String localIp = getLocalIntranetIp();
log.info("本地内网IP: {}", localIp);
// 获取所有内网IP
List<String> allIps = getAllLocalIntranetIps();
log.info("所有本地内网IP: {}", allIps);
// 获取首选内网IP
String preferredIp = getPreferredLocalIntranetIp();
log.info("首选内网IP: {}", preferredIp);
// 获取主机名
String hostname = getLocalHostName();
log.info("本地主机名: {}", hostname);
// 获取IP和主机名
String ipWithHostname = getLocalIpWithHostName();
log.info("IP和主机名: {}", ipWithHostname);
}
这些方法会自动过滤掉回环地址和非内网地址,返回真正的本地内网 IP 地址。getPreferredLocalIntranetIp() 方法按照常用网段的优先级返回最合适的 IP 地址。
典型场景下的不同结果
场景 1:普通家用电脑
第一个内网IP: 192.168.1.100
所有内网IP: [192.168.1.100]
首选内网IP: 192.168.1.100
结果: 三个方法返回相同
场景 2:开发者电脑(Docker + VPN)
第一个内网IP: 172.17.0.1 (Docker网桥)
所有内网IP: [172.17.0.1, 10.0.2.15, 192.168.1.100]
首选内网IP: 192.168.1.100 (优先选择192.168网段)
结果: 首选方法返回更合适的IP
场景 3:服务器(多网卡)
第一个内网IP: 10.0.1.50 (第一个网卡)
所有内网IP: [10.0.1.50, 192.168.100.10, 172.20.0.5]
首选内网IP: 192.168.100.10 (优先192.168网段)
结果: 首选方法选择了业务网段
推荐使用场景
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
getLocalIntranetIp() |
简单应用,只需一个 IP | 快速、简单 | 可能返回虚拟网络 IP |
getAllLocalIntranetIps() |
网络诊断、用户选择 | 信息完整 | 需要额外处理逻辑 |
getPreferredLocalIntranetIp() |
服务绑定、配置生成 | 智能选择 | 逻辑相对复杂 |
建议: 大多数情况下使用 getPreferredLocalIntranetIp(),它能提供最合适的结果。
相关文章