首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java獲取本機與遠程IP地址:InetAddress實戰指南

     編輯:Java 相關知識

java.net.InetAddress是Java網絡編程的基石,提供主機名/IP地址解析、本機網卡枚舉、可達性測試等核心功能。

核心API速覽

方法用途阻塞性
getLocalHost()獲取本機InetAddress可能阻塞(DNS查詢)
getByName(host)解析主機名/IP阻塞(DNS查詢)
getAllByName(host)獲取所有解析地址阻塞
getHostAddress()獲取IP字符串非阻塞
getHostName()獲取主機名可能阻塞(反向DNS)
isReachable(timeout)ICMP/TCP可達性測試阻塞

基本用法範例


public class IPDetector {
    public static void main(String[] args) {
        try {
            // 1. 本機信息
            InetAddress local = InetAddress.getLocalHost();
            System.out.println("本機主機名: " + local.getHostName());
            System.out.println("本機IP: " + local.getHostAddress());
            
            // 2. 遠程服務器解析
            InetAddress server = InetAddress.getByName("www.bianceng.cn");
            System.out.println("服務器IP: " + server.getHostAddress());
            
            // 3. 多IP解析(負載均衡/集群)
            InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
            for (InetAddress addr : addresses) {
                System.out.println("  - " + addr.getHostAddress());
            }
            
        } catch (UnknownHostException e) {
            System.err.println("DNS解析失敗: " + e.getMessage());
        }
    }
}

進階:枚舉所有網卡IP(多網卡/虛擬機/容器環境必須)


import java.net.NetworkInterface;
import java.net.InetAddress;
import java.util.Enumeration;

public class AllIPs {
    public static void main(String[] args) throws Exception {
        Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
        
        while (interfaces.hasMoreElements()) {
            NetworkInterface ni = interfaces.nextElement();
            
            // 過濾回環/關閉/虛擬接口
            if (ni.isLoopback() || !ni.isUp() || ni.isVirtual()) continue;
            
            System.out.println("網卡: " + ni.getDisplayName() + " [" + ni.getName() + "]");
            
            Enumeration addresses = ni.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress addr = addresses.nextElement();
                // 只顯示IPv4
                if (addr instanceof java.net.Inet4Address) {
                    System.out.println("  IPv4: " + addr.getHostAddress());
                }
            }
        }
    }
}

常見陷阱與最佳實踐

1. getLocalHost()陷阱

  • 可能返回127.0.0.1(/etc/hosts配置問題)
  • 多網卡環境返回不確定
  • 解決:使用NetworkInterface枚舉擇優選擇

2. 阻塞風險

  • DNS解析無超時控制,可能無限阻塞
  • 解決:異步線程池執行,或使用CompletableFuture帶超時

3. IPv6兼容


// 兼雙棧環境優先IPv4
InetAddress addr = InetAddress.getByName(host);
if (addr instanceof Inet6Address) {
    // 嘗試獲取IPv4
    for (InetAddress a : InetAddress.getAllByName(host)) {
        if (a instanceof Inet4Address) return a;
    }
}
return addr;

生產級工具類封裝


public final class NetUtils {
    private NetUtils() {}
    
    /** 獲取首選業務IP(非回環、IPv4、啟用狀態) */
    public static String getPreferredIp() {
        try {
            Enumeration nis = NetworkInterface.getNetworkInterfaces();
            while (nis.hasMoreElements()) {
                NetworkInterface ni = nis.nextElement();
                if (ni.isLoopback() || !ni.isUp()) continue;
                
                Enumeration ias = ni.getInetAddresses();
                while (ias.hasMoreElements()) {
                    InetAddress ia = ias.nextElement();
                    if (ia instanceof Inet4Address && !ia.isLoopbackAddress()) {
                        return ia.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            log.warn("獲取IP失敗", e);
        }
        return "127.0.0.1"; // 兜底
    }
    
    /** 異步解析帶超時 */
    public static CompletableFuture resolveAsync(String host, long timeoutMs) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return InetAddress.getByName(host).getHostAddress();
            } catch (Exception e) {
                throw new CompletionException(e);
            }
        }).orTimeout(timeoutMs, TimeUnit.MILLISECONDS)
          .exceptionally(e -> "解析失敗: " + e.getCause().getMessage());
    }
}

理解InetAddress阻塞特性、多網卡枚舉邏輯、IPv4/IPv6共存處理,是構建高可用網絡應用的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved