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

Java 透過網卡名稱獲取 IP 位址完整實作

     編輯:Java 程式設計入門

需求背景

在多網卡環境(如同時擁有乙太網路、Wi-Fi、VPN、虛擬網卡)下,精確獲取指定網卡的 IP 位址是常見需求。本文提供完整實作,支援 IPv4/IPv6、子介面遍歷、回環/虛擬網卡過濾。

核心實作程式碼

package com.example.network;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.List;

public class NetworkInterfaceUtil {

    /**
     * 根據網卡名稱獲取所有 IP 位址
     * @param interfaceName 網卡名稱 (如 "eth0", "wlan0", "lo")
     * @return IP 位址列表,包含 IPv4 與 IPv6
     */
    public static List<InetAddress> getInetAddressesByName(String interfaceName) {
        List<InetAddress> addresses = new ArrayList<>();
        try {
            NetworkInterface ni = NetworkInterface.getByName(interfaceName);
            if (ni == null) {
                System.err.println("找不到網卡: " + interfaceName);
                return addresses;
            }
            Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
            while (inetAddresses.hasMoreElements()) {
                addresses.add(inetAddresses.nextElement());
            }
            // 遞迴處理子介面
            addresses.addAll(getSubInterfaceAddresses(ni));
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return addresses;
    }

    /**
     * 遞迴獲取子介面 IP
     */
    private static List<InetAddress> getSubInterfaceAddresses(NetworkInterface parent) {
        List<InetAddress> subAddresses = new ArrayList<>();
        try {
            Enumeration<NetworkInterface> subInterfaces = parent.getSubInterfaces();
            while (subInterfaces.hasMoreElements()) {
                NetworkInterface sub = subInterfaces.nextElement();
                Enumeration<InetAddress> addrs = sub.getInetAddresses();
                while (addrs.hasMoreElements()) {
                    subAddresses.add(addrs.nextElement());
                }
                // 繼續遞迴更深層子介面
                subAddresses.addAll(getSubInterfaceAddresses(sub));
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return subAddresses;
    }

    /**
     * 列出所有網卡與 IP(除錯用)
     */
    public static void listAllInterfaces() {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = interfaces.nextElement();
                System.out.println("=== 網卡: " + ni.getName() + " (顯示名: " + ni.getDisplayName() + ") ===");
                Enumeration<InetAddress> addrs = ni.getInetAddresses();
                while (addrs.hasMoreElements()) {
                    InetAddress addr = addrs.nextElement();
                    System.out.println("  IP: " + addr.getHostAddress() + " [" + (addr instanceof java.net.Inet4Address ? "IPv4" : "IPv6") + "]");
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    // 測試主程式
    public static void main(String[] args) {
        // 列出所有網卡供參考
        listAllInterfaces();

        System.out.println("\n--- 獲取 lo (回環) 介面 IP ---");
        List<InetAddress> loAddresses = getInetAddressesByName("lo");
        for (InetAddress addr : loAddresses) {
            System.out.println("IP: " + addr.getHostAddress());
        }
    }
}

關鍵 API 解析

方法用途備註
NetworkInterface.getByName(name)直接按名稱查找網卡比遍歷所有網卡效率高
getInetAddresses()獲取該介面綁定的所有 IP包含 IPv4、IPv6、連結本地址
getSubInterfaces()獲取虛擬/子介面 (如 eth0:1)Linux 常見多 IP 配置場景
isUp() / isLoopback() / isVirtual()過濾啟用/回環/虛擬介面實際部署建議加入過濾邏輯

跨平台網卡命名差異

作業系統實體網卡回環介面虛擬介面
Linuxeth0, ens33, enp3s0loeth0:1, docker0, vethxxx
Windows乙太網路, Wi-Fi, 本地連線*Loopback Pseudo-Interface 1Hyper-V, VMware Network Adapter
macOSen0, en1lo0bridge0, utun0

進階過濾實用方法

/**
 * 獲取第一個非回環、非虛擬、已啟用的 IPv4 位址
 */
public static String getPrimaryIpv4Address() {
    try {
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface ni = interfaces.nextElement();
            if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) continue;

            Enumeration<InetAddress> addrs = ni.getInetAddresses();
            while (addrs.hasMoreElements()) {
                InetAddress addr = addrs.nextElement();
                if (addr instanceof java.net.Inet4Address) {
                    return addr.getHostAddress();
                }
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
    }
    return null;
}

常見坑點與解決

  1. 權限問題:Linux 讀取部分網卡資訊需 root 權限,建議服務以適當權限運行
  2. IPv6 連結本地址:fe80::% 開頭為連結本地址,非對外可路由 IP,商業邏輯通常需過濾
  3. 介面名稱變動:系統重啟或熱插拔後介面名可能改變,避免硬編碼,改用特徵識別(如 MAC 位址、IP 段)
  4. Windows 顯示名 vs 實際名:getDisplayName() 回傳友善名稱,getName() 為系統內部名,API 參數需用後者

總結

Java NetworkInterface API 提供完整網卡資訊存取能力。實務上建議封裝工具類,支援按名稱查詢、子介面遞迴、IP 版本過濾、介面狀態過濾。跨平台部署時務必實測目標環境網卡命名規則,並加入適當異常處理與日誌記錄。

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