Java 网络编程(1):使用 NetworkInterface 得到本机在局域网内的 IP 地址

一、问题提出

在使用 Java 开发网络程序时,有时候咱们须要知道本机在局域网中的 IP 地址。很常见的一种作法是调用本地命令(好比 Windows 上的 ipconfig 命令和 Linux 上的 ifconfig 命令),接着解析本地命令的输出,最后获得本机在局域网内的 IP 地址。很明显,这种作法不够方便,也不够 Java。因而引出了 Java 在 JDK1.4 的时候添加的一个类: NetworkInterfacejava

二、寻找方法

顾名思义,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

ipconfig的结果

能够发现开发

网卡接口名称: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 地址的功能。

相关文章
相关标签/搜索