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

Java 網路程式設計精通指南(11):NetworkInterface — 獲取本機網卡與 IP 完整指南

     編輯:Java 相關知識

JDK 1.4 引入 java.net.NetworkInterface,統一提供物理網卡、虛擬網卡(VMware、Docker、VPN 等)及邏輯介面(回環、PPP、IPv6 隧道)的信息查詢能力。本文系統講解創建對象、枚舉所有介面、核心 getter 方法及實戰應用。

一、創建 NetworkInterface 對象的兩種靜態工廠方法

1. getByName(String name) — 按介面名查找

介面名由作業系統分配,常見格式:

  • Linux/Unix: eth0, eth1, lo (回環)
  • Windows: 以太網, WLAN, 本地連接* 等顯示名,或內部名如 eth0 (視驅動而定)
  • PPP/VPN: ppp0, tun0
NetworkInterface ni = NetworkInterface.getByName("eth0");
if (ni == null) System.out.println("介面不存在");
else System.out.println(ni); // toString() 輸出 name, displayName, 綁定 IPs

2. getByInetAddress(InetAddress addr) — 按 IP 反查介面

確定某個本地 IP 所屬介面。**參數必須是本地 IP**,遠程 IP 會返回 null。

InetAddress localIp = InetAddress.getByName("192.168.1.100");
NetworkInterface ni = NetworkInterface.getByInetAddress(localIp);
// 返回綁定該 IP 的介面 (如 eth0)

ADSL 撥號 IP 通常屬於 ppp0 介面。

二、枚舉所有網絡介面 — getNetworkInterfaces()

Enumeration nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
    NetworkInterface ni = nis.nextElement();
    System.out.println(ni); // 打印完整信息
    // 或按需提取
    System.out.println("Name: " + ni.getName());
    System.out.println("Display: " + ni.getDisplayName());
    Enumeration ips = ni.getInetAddresses();
    while (ips.hasMoreElements()) {
        System.out.println("  IP: " + ips.nextElement().getHostAddress());
    }
}

典型輸出 (Windows + VMware + ADSL)

name:lo (MS TCP Loopback interface) index:1
  IP: 127.0.0.1
  IP: 0:0:0:0:0:0:0:1 (::1)
name:eth0 (Realtek RTL8139 Family PCI Fast Ethernet NIC) index:4
  IP: 192.168.18.10
  IP: 192.168.18.20
name:ppp0 (WAN (PPP/SLIP) Interface) index:0
  IP: 218.61.151.22 (ADSL 動態公網 IP)
name:VMware Network Adapter VMnet1 index:5
  IP: 192.168.83.1
name:VMware Network Adapter VMnet8 index:6
  IP: 192.168.189.1

三、核心 Getter 方法

方法返回值說明
getName()String系統內部名 (eth0, lo, ppp0...)
getDisplayName()String友好顯示名 (Windows 下為網卡描述,Unix 下常同 getName)
getInetAddresses()Enumeration<InetAddress>該介面綁定的所有 IP (IPv4 + IPv6)
getIndex()int介面索引 (內核分配)
isUp()boolean介面是否啟用
isLoopback()boolean是否回環介面
isPointToPoint()boolean是否點對點 (PPP, VPN)
supportsMulticast()boolean是否支持組播
getHardwareAddresses()byte[] (MAC)物理地址 (MAC),虛擬介面可能為空
getMTU()int最大傳輸單元
getSubInterfaces()Enumeration<NetworkInterface>子介面 (VLAN, IP 別名等)

四、實戰應用場景

  1. 服務綁定特定網卡:獲取目標介面的 IP,傳給 Socket.bind() 或 ServerSocket.bind()。
  2. 多網卡路由選擇:根據目標 IP 選擇出口介面,配合 isReachable(netif, ...)。
  3. 獲取 MAC 地址做授權/標識:ni.getHardwareAddresses() (需過濾虛擬介面)。
  4. 網路拓撲發現/監控:枚舉所有介面、IP、MTU、狀態,上報監控系統。
  5. 容器/雲環境網路診斷:識別 docker0, veth*, cni0 等虛擬介面。

代碼片段:獲取首個非回環、啟用、有 IPv4 的物理網卡 IP

public static InetAddress getPrimaryIpv4() throws SocketException {
    Enumeration nis = NetworkInterface.getNetworkInterfaces();
    while (nis.hasMoreElements()) {
        NetworkInterface ni = nis.nextElement();
        if (ni.isLoopback() || !ni.isUp() || ni.isPointToPoint()) continue;
        Enumeration ips = ni.getInetAddresses();
        while (ips.hasMoreElements()) {
            InetAddress ip = ips.nextElement();
            if (ip instanceof Inet4Address) return ip; // 找到第一個 IPv4
        }
    }
    return null;
}

注意事項

  • 需要 SocketPermission "resolve" 權限 (SecurityManager 環境下)。
  • 虛擬介面 (VMware, Docker, VPN) 會大量出現,業務邏輯需過濾 isPointToPoint()、displayName 關鍵字。
  • IPv6 地址 (link-local, global, ULA) 同樣包含在 getInetAddresses() 中,需用 instanceof Inet6Address 區分。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved