原文地址:https://segmentfault.com/a/1190000007462741

1、问题提出

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

2、寻找方法

顾名思义,NetworkInterface 用于表示一个网络接口,这可以是一个物理的网络接口,也可以是一个虚拟的网络接口,而一个网络接口通常由一个 IP 地址来表示。既然 NetworkInterface 用来表示一个网络接口,那么如果可以获得当前机器所有的网络接口(包括物理的和虚拟的),然后筛选出表示局域网的那个网络接口,那就可以得到机器在局域网内的 IP 地址。

查看 NetworkInterface 类的所有方法,发现如下两个方法:

public static Enumeration getNetworkInterfaces()

通过 API 文档可知,使用 getNetworkInterfaces 方法即可得到当前机器上所有的网络接口。

public Enumeration getInetAddresses()

通过 API 文档可知,getInetAddresses 方法返回绑定到该网卡的所有的 IP 地址。(虽然一个网络接口确实可以绑定多个 IP 地址,然而通常情况下,一个网络接口都是只对应一个 IP 地址)

3、实践

OK,现在让电脑连接上 WiFi,来实践下 NetworkInterface 的功能。

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 命令得到的结果:

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 getInterfaceAddresses()

getInterfaceAddresses 方法的作用与 getInetAddresses 方法类似,但是返回的是一个绑定到该网络接口的所有 InterfaceAddress 的集合。InterfaceAddress 也是 JDK1.6 之后添加的类,相比于 InetAddress 的区别在于它除了具有一个 IP 地址(InetAddress),还包括了该地址对应的广播地址和掩码长度。

4、总结

当然,使用 NetworkInterface 类来获取机器在局域网内的 IP 地址还是有一定的平台相关性,但是相比于使用本地命令的方式来说,会更加方便和更加的 Java 。

PS:在 Android 平台上同样可以使用 NetworkInterface 来实现获得机器在局域网内 IP 地址的功能。

Java 网络编程(1):使用 NetworkInterface 获得本机在局域网内的 IP 地址的更多相关文章

  1. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  2. JAVA网络编程【转】出处不详

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  3. 【转】JAVA 网络编程

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  4. Java网络编程技术1

    1. Java网络编程常用API 1.1 InetAddress类使用示例 1.1.1根据域名查找IP地址 获取用户通过命令行方式指定的域名,然后通过InetAddress对象来获取该域名对应的IP地 ...

  5. java网络编程+通讯协议的理解

    参考: http://blog.csdn.net/sunyc1990/article/details/50773014 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很 ...

  6. Java网络编程技术2

    3. UDP数据报通信 UDP通信中,需要建立一个DatagramSocket,与Socket不同,它不存在“连接”的概念,取而代之的是一个数据报包——DatagramPacket.这个数据报包必须知 ...

  7. 20145205 《Java程序设计》实验报告五:Java网络编程及安全

    20145205 <Java程序设计>实验报告五:Java网络编程及安全 实验要求 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.客户端中输入明文,利用DES算法加密,D ...

  8. Java 网络编程学习总结

    新手一枚,Java学习中,把自己学习网络编程的知识总结一下,梳理下知识,方便日后查阅,高手莫进. 本文的主要内容: [1]    网络编程认识                [2]  TCP/IP编程 ...

  9. 20145212 实验五《Java网络编程》

    20145212 实验五<Java网络编程> 一.实验内容 1.运行下载的TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成 ...

随机推荐

  1. Office应用程序对照表

    任何Office应用程序(包括excel)的类型库都作为Office安装的一部分安装.类型库是特定于版本的(即,安装了哪个版本的Office). 例如,Office 2007版本为12.0,Offic ...

  2. 数据结构和算法设计专题之---二分查找(Java版)

    1.前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序 2.原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后:将要查找的值和数组的中值 ...

  3. Peer模式的多线程程序例子

    Peer模式的多线程程序例子 程序的模型大概是这样的.有一个master(),用来分发任务.有N个多线程的slave用来处理任务. 主程序里可以这样调用: 可以看出,上面这段程序还是依赖于Proces ...

  4. npm install 超时 国内 切换源; npm ERR! code ELIFECYCLE;

    install 超时 查看npm源地址 npm config get registry #http://registry.npmjs.org 为国外镜像地址 设置阿里云镜像 npm config se ...

  5. thinkphp5操作redis系列教程】列表类型之lRange,lGetRange

    <?php namespace app\admin\controller; use think\cache\driver\Redis; use think\Controller; use \th ...

  6. 不带头结点的单链表------C语言实现

    File name:no_head_link.c Author:SimonKly Version:0.1 Date: 2017.5.20 Description:不带头节点的单链表 Funcion L ...

  7. 装机时键盘选择失误?教你修改kali Linux键盘到美式。

    在Linux装机选择键盘的时候,由于学的是英式英语而选择了英式键盘,结果吃了大亏.英式键盘和我们平时使用的美式键盘的键位是不一样的! 这是我们平时使用的美式键盘: 这是英式键盘: 修改的方式是: 点击 ...

  8. k小子串 SPOJ - SUBLEX 2

    题意: 求字典序第K大的子串 题解: 先求出后缀自动机对应节点 // 该节点后面所形成的自字符串的总数 然后直接模拟即可 #include <set> #include <map&g ...

  9. ECMS清除挂马以及后台升级实战(从ecms6.6~ecms7.0)

    当时状况 Windows Server 2008 R2 Enterprise + 帝国CMS6.6 + MySql   server软件: Microsoft-IIS/7.5 操作系统: WINNT ...

  10. sanic中间件和监听器

    一:中间件 中间件是服务器在请求之前或之后执行的功能,他们可以用来修改修改用户定义处理函数的请求或相应. Sanic提供两种类型的中间件:请求和响应. 两者都是使用@app.middleware装饰器 ...