在使用 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 地址的功能。