在使用 Java 開發網絡程序時,有時候咱們須要知道本機在局域網中的 IP 地址。很常見的一種作法是調用本地命令(好比 Windows 上的 ipconfig 命令和 Linux 上的 ifconfig 命令),接着解析本地命令的輸出,最後獲得本機在局域網內的 IP 地址。很明顯,這種作法不夠方便,也不夠 Java。因而引出了 Java 在 JDK1.4 的時候添加的一個類: NetworkInterface 。java
顧名思義,NetworkInterface 用於表示一個網絡接口,這能夠是一個物理的網絡接口,也能夠是一個虛擬的網絡接口,而一個網絡接口一般由一個 IP 地址來表示。既然 NetworkInterface 用來表示一個網絡接口,那麼若是能夠得到當前機器全部的網絡接口(包括物理的和虛擬的),而後篩選出表示局域網的那個網絡接口,那就能夠獲得機器在局域網內的 IP 地址。網絡
查看 NetworkInterface 類的全部方法,發現以下兩個方法:spa
public static Enumeration<NetworkInterface> getNetworkInterfaces()
經過 API 文檔可知,使用 getNetworkInterfaces 方法便可獲得當前機器上全部的網絡接口。.net
public Enumeration<InetAddress> getInetAddresses()
經過 API 文檔可知,getInetAddresses 方法返回綁定到該網卡的全部的 IP 地址。(雖然一個網絡接口確實能夠綁定多個 IP 地址,然而一般狀況下,一個網絡接口都是隻對應一個 IP 地址)code
OK,如今讓電腦鏈接上 WiFi,來實踐下 NetworkInterface 的功能。blog
import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; public class NetworkInterfaceTest { public static void main(String[] args) throws Exception { // 得到本機的全部網絡接口 Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); while (nifs.hasMoreElements()) { NetworkInterface nif = nifs.nextElement(); // 得到與該網絡接口綁定的 IP 地址,通常只有一個 Enumeration<InetAddress> addresses = nif.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); if (addr instanceof Inet4Address) { // 只關心 IPv4 地址 System.out.println("網卡接口名稱:" + nif.getName()); System.out.println("網卡接口地址:" + addr.getHostAddress()); System.out.println(); } } } } }
在我機器(Windows10)上運行結果:接口
對比使用 ipconfig 命令獲得的結果:ip
能夠發現開發
網卡接口名稱:wlan1 網卡接口地址:192.168.3.5
即爲機器在局域網內的 IP 地址 —— Windows 平臺上局域網的網絡接口以「wlan」開頭。(lo 爲本地迴環地址,eth0 和 eth4 爲 VMware 建立的虛擬地址)文檔
因而咱們能夠寫出一個簡單的在 Windows 機器上得到局域網 IP 地址的方法:
public InetAddress getLANAddressOnWindows() { try { Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); while (nifs.hasMoreElements()) { NetworkInterface nif = nifs.nextElement(); if (nif.getName().startsWith("wlan")) { Enumeration<InetAddress> addresses = nif.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); if (addr.getAddress().length == 4) { // 速度快於 instanceof return addr; } } } } } catch (SocketException ex) { ex.printStackTrace(System.err); } return null; }
(該方法沒有考慮 Windows 平臺上有多個網絡接口的名稱以 「wlan」 開頭的狀況,好比你的機器鏈接了 WiFi,而後又使用該機器做爲熱點 —— 不過很容易對兩者進行區分,請有興趣的讀者本身實踐)
在 JDK1.6 時 NetworkInterface 還添加了一個新的方法:
public List<InterfaceAddress> getInterfaceAddresses()
getInterfaceAddresses 方法的做用與 getInetAddresses 方法相似,可是返回的是一個綁定到該網絡接口的全部 InterfaceAddress 的集合。InterfaceAddress 也是 JDK1.6 以後添加的類,相比於 InetAddress 的區別在於它除了具備一個 IP 地址(InetAddress),還包括了該地址對應的廣播地址和掩碼長度。
固然,使用 NetworkInterface 類來獲取機器在局域網內的 IP 地址仍是有必定的平臺相關性,可是相比於使用本地命令的方式來講,會更加方便和更加的 Java 。PS:在 Android 平臺上一樣可使用 NetworkInterface 來實現得到機器在局域網內 IP 地址的功能。