Java 实例 – 获取本机ip地址及主机名(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Java 网络编程中,获取本机的 IP 地址及主机名是许多应用程序开发的基础需求。例如,开发聊天工具时需要标识本地设备,构建服务器端应用时需要确认服务绑定地址,甚至在调试网络问题时也需要快速定位本机信息。然而,对于编程初学者而言,如何通过 Java 代码高效、准确地获取这些信息可能充满困惑。本文将以“Java 实例 – 获取本机ip地址及主机名”为主题,从基础概念到代码实现,逐步解析这一过程,并提供可直接复用的代码示例。


网络编程基础概念

IP 地址与主机名

IP 地址是设备在网络中的唯一标识,类似于“数字地址”。例如,192.168.1.2 是常见的内网地址,而 8.8.8.8 是 Google 的公共 DNS 服务器地址。主机名则是更易读的名称,例如 localhost 对应 127.0.0.1。两者通过 DNS(域名系统)相互映射。

网络接口(Network Interface)

网络接口可以理解为设备连接网络的“端口”,例如以太网卡、Wi-Fi 或虚拟网卡。每个接口可能绑定多个 IP 地址(IPv4 和 IPv6)。Java 中的 NetworkInterface 类用于操作这些接口。

比喻
想象一个邮局(网络接口),它负责接收和发送信件(网络数据)。邮局的地址(IP 地址)决定了信件的投递方向,而邮局的名称(主机名)是更人性化的标识。


方法一:使用 InetAddress 类获取本机 IP 地址

Java 的 java.net.InetAddress 类提供了直接获取本机 IP 的方法。

代码示例 1:基础实现

import java.net.InetAddress;  
import java.net.UnknownHostException;  

public class HostInfoDemo {  
    public static void main(String[] args) {  
        try {  
            InetAddress localHost = InetAddress.getLocalHost();  
            System.out.println("本机 IP 地址:" + localHost.getHostAddress());  
            System.out.println("本机主机名:" + localHost.getHostName());  
        } catch (UnknownHostException e) {  
            System.out.println("无法获取本机信息!");  
            e.printStackTrace();  
        }  
    }  
}  

关键点解析

  1. InetAddress.getLocalHost()
    该方法返回一个 InetAddress 对象,包含本机的 IP 和主机名。
  2. getHostAddress()
    返回 IP 地址的字符串形式(如 192.168.1.2)。
  3. getHostName()
    返回主机名(如 my-desktop)。

局限性

  • 可能获取到回环地址
    若本机未正确配置网络,可能返回 127.0.0.1(IPv4)或 ::1(IPv6)。
  • 依赖系统配置
    主机名由操作系统提供,若 DNS 配置错误可能导致异常(如 UnknownHostException)。

方法二:通过 NetworkInterface 类遍历所有网络接口

若需获取所有有效 IP 地址(例如排除回环地址),需结合 NetworkInterface 类进行更精细的操作。

代码示例 2:遍历网络接口

import java.net.*;  
import java.util.*;  

public class NetworkInterfaceDemo {  
    public static void main(String[] args) {  
        try {  
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();  
            List<String> ips = new ArrayList<>();  

            while (interfaces.hasMoreElements()) {  
                NetworkInterface ni = interfaces.nextElement();  
                Enumeration<InetAddress> addresses = ni.getInetAddresses();  

                while (addresses.hasMoreElements()) {  
                    InetAddress addr = addresses.nextElement();  
                    if (!addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) {  
                        ips.add(addr.getHostAddress());  
                    }  
                }  
            }  

            System.out.println("有效 IP 地址列表:" + ips);  
        } catch (SocketException e) {  
            e.printStackTrace();  
        }  
    }  
}  

关键点解析

  1. NetworkInterface.getNetworkInterfaces()
    返回所有网络接口的枚举对象。
  2. 过滤无效地址
    • isLoopbackAddress():排除回环地址(如 127.0.0.1)。
    • isLinkLocalAddress():排除链路本地地址(如 169.254.x.x,未获取到 DHCP 地址时的默认值)。

比喻
这就像在邮局中筛选出所有“活跃的”投递地址,排除测试地址或临时地址。


获取主机名的方法

代码示例 3:直接获取主机名

public class HostNameDemo {  
    public static void main(String[] args) {  
        try {  
            String hostName = InetAddress.getLocalHost().getHostName();  
            System.out.println("主机名:" + hostName);  
        } catch (UnknownHostException e) {  
            System.out.println("无法获取主机名!");  
        }  
    }  
}  

注意事项

  • DNS 解析问题
    若主机名无法解析为 IP(如配置错误),InetAddress.getLocalHost() 可能抛出异常。
  • 跨平台差异
    Windows 系统可能依赖 C:\Windows\System32\drivers\etc\hosts 文件配置主机名,而 Linux/Unix 系统通常通过 /etc/hostname 文件。

实际案例:综合实现获取所有有效 IP 地址

以下代码结合了 NetworkInterface 和异常处理,生成最终可用的 IP 列表:

import java.net.*;  
import java.util.*;  

public class HostInfoCollector {  
    public static List<String> getValidIPs() {  
        List<String> ips = new ArrayList<>();  
        try {  
            Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();  
            while (nis.hasMoreElements()) {  
                NetworkInterface ni = nis.nextElement();  
                if (ni.isLoopback() || !ni.isUp()) {  
                    continue; // 排除回环和未启用的接口  
                }  
                Enumeration<InetAddress> addrs = ni.getInetAddresses();  
                while (addrs.hasMoreElements()) {  
                    InetAddress addr = addrs.nextElement();  
                    if (!addr.isLoopbackAddress() &&  
                        !addr.isLinkLocalAddress() &&  
                        !addr.isAnyLocalAddress()) {  
                        ips.add(addr.getHostAddress());  
                    }  
                }  
            }  
        } catch (SocketException e) {  
            e.printStackTrace();  
        }  
        return ips;  
    }  

    public static void main(String[] args) {  
        List<String> ips = getValidIPs();  
        System.out.println("有效 IP 地址:" + ips);  
    }  
}  

逻辑说明

  1. 过滤接口状态
    • isLoopback():排除回环接口。
    • isUp():仅处理启用的接口(如已连接的 Wi-Fi)。
  2. 过滤地址类型
    • isAnyLocalAddress():排除 0.0.0.0 等预留地址。

注意事项与最佳实践

1. 跨平台兼容性

  • Windows/Linux 差异
    在 Linux 中,虚拟接口(如 docker0)可能生成额外 IP,需根据需求过滤。
  • 虚拟化环境
    虚拟机或容器(如 Docker)可能分配独立 IP,需确认代码是否适配。

2. 异常处理

  • 权限问题
    在某些系统中,获取网络接口信息可能需要管理员权限(如 Windows 防火墙限制)。
  • 网络未连接
    若设备未连接网络,NetworkInterface 可能返回空枚举。

3. 性能优化

  • 缓存结果
    IP 地址通常在程序运行期间不变,可缓存首次获取的结果,避免重复计算。

扩展应用:结合 HTTP 请求获取公网 IP

若需获取本机的公网 IP(如通过路由器映射的外网地址),可通过访问第三方 API 实现。例如:

import java.io.BufferedReader;  
import java.io.InputStreamReader;  
import java.net.HttpURLConnection;  
import java.net.URL;  

public class PublicIPFetcher {  
    public static String getPublicIP() {  
        try {  
            URL url = new URL("https://api.ipify.org");  
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
            connection.setRequestMethod("GET");  
            BufferedReader reader = new BufferedReader(  
                new InputStreamReader(connection.getInputStream())  
            );  
            return reader.readLine();  
        } catch (Exception e) {  
            return "无法获取公网 IP";  
        }  
    }  

    public static void main(String[] args) {  
        System.out.println("公网 IP 地址:" + getPublicIP());  
    }  
}  

使用场景

此方法适用于需要暴露本地服务到外网(如远程调试或云服务器管理)的场景。


总结

本文通过代码实例与分步解析,详细介绍了 Java 中获取本机 IP 地址及主机名的多种方法。对于初学者,建议从 InetAddress 入手,逐步探索 NetworkInterface 的高级用法;中级开发者可结合异常处理与跨平台优化,实现更健壮的解决方案。掌握这些技术后,开发者可以轻松将 IP 地址信息集成到日志记录、设备标识或网络通信的业务逻辑中,为后续的复杂网络编程打下坚实基础。

通过本文的学习,读者不仅能解决“Java 实例 – 获取本机ip地址及主机名”的具体问题,还能理解底层网络接口的运作原理,为深入学习 Java 网络编程铺平道路。

最新发布