java如何获取mac物理地址

前言

原本以为这功能调用一个api就完事了,然而,查了一下没那么简单,网上查的资料实在忍不住要拿出来说说,估计真的都没有试过其他环境,而且,估计连背后的原理都没了解就用了。。
下面先说说找到的几份资料:

ps:本机相关ip信息:
在这里插入图片描述

第一篇参考

Java获取本机MAC地址

点评:实际运行效果如下:
在这里插入图片描述
空指针啊。。。那么我们如果换个ip来试试?

第二篇参考

使用java获取本机mac

看看代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class getmac{
public static String getLinuxMACAddress() {
String mac = null;
BufferedReader bufferedReader = null;
Process process = null;
try {
process = Runtime.getRuntime().exec(“ifconfig enp4s0”);
bufferedReader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = null;
int index = -1;
while ((line = bufferedReader.readLine()) != null) {
index = line.toLowerCase().indexOf(“硬件地址”);

            if (index != -1) {
                
                mac = line.substring(index + 4).trim();
                break;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        bufferedReader = null;
        process = null;
    }
    return mac;
}

public static void main(String[] argc) {
String mac = getLinuxMACAddress();
System.out.println(“本地是Linux系统, MAC地址是:” + mac);

}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

一运行:
在这里插入图片描述

还是不行。。里面几行代码我有点在意:

process = Runtime.getRuntime().exec("ifconfig enp4s0");

index = line.toLowerCase().indexOf(“硬件地址”);

  • 1
  • 2
  • 3
  • 4
  • 5

调用命令ifconfig enp4s0 然后根据字符串“硬件地址”来截取字符,获得mac地址

这样做估计不行,部署到正式环境分分钟挂掉机器

首先:
不同机器的enp这些东西是不一样的:
在这里插入图片描述
其次,“硬件地址”这个字符串估计在不同机器上面有不同的解释吧。。。

第三份资料

How can i get list of MAC address and IP address of computer through java?

为了方便查看,我抄一下【墙的强度略大,google的js脚本都卡掉了,估计大家都是卡五六分钟才看到的,我懂】

在这里插入图片描述

在这里插入图片描述

两段代码如下:

           InetAddress ip;
    ip = InetAddress.getLocalHost();
    System.out.println("Current IP address : " + ip.getHostAddress());
NetworkInterface network = NetworkInterface.getByInetAddress(ip);

byte[] mac = network.getHardwareAddress();

System.out.print("Current MAC address : ");

StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
    sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));        
}
System.out.println(sb.toString());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

                    java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
        en.hasMoreElements(); ) {
        NetworkInterface iface = en.nextElement();
        List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
        //For each network interfaces iterate through each ip address
        for(InterfaceAddress addr : addrs) {
                         ip = addr.getAddress();
                          //Process the IP ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

好了,根据以上回答及代码,补充完整,然后查看结果

单地址:

package test;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

public class SingleNetAddress {
/*
* @param args
* @throws UnknownHostException
* @throws SocketException
*/
public static void main(String[] args) throws UnknownHostException, SocketException {

    System.out.println("进行single net address 测试===》");

    InetAddress ip;
    ip = InetAddress.getLocalHost();
    System.out.println("Current IP address : " + ip.getHostAddress());

    NetworkInterface network = NetworkInterface.getByInetAddress(ip);

    byte[] mac = network.getHardwareAddress();

    System.out.print("Current MAC address : ");

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i &lt; mac.length; i++) {
        sb.append(String.format("%02X%s", mac[i], (i &lt; mac.length - 1) ? "-" : ""));
    }
    System.out.println(sb.toString());

}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

运行结果:

在这里插入图片描述

不行,还是出错了。。

多地址的:

package test;

import java.net.*;
import java.util.List;

public class MultiNetAddress {
/*
* @param args
* @throws UnknownHostException
* @throws SocketException
*/
public static void main(String[] args) throws UnknownHostException, SocketException {
System.out.println(“进行 multi net address 测试===》”);
java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while(en.hasMoreElements()){
NetworkInterface iface = en.nextElement();
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
//For each network interfaces iterate through each ip address
//For each network interfaces iterate through each ip address
for(InterfaceAddress addr : addrs) {
InetAddress ip = addr.getAddress();
System.out.println("Current IP address : " + ip.getHostAddress());

            NetworkInterface network = NetworkInterface.getByInetAddress(ip);

            byte[] mac = network.getHardwareAddress();

            System.out.print("Current MAC address : ");

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; mac.length; i++) {
                sb.append(String.format("%02X%s", mac[i], (i &lt; mac.length - 1) ? "-" : ""));
            }
            System.out.println(sb.toString());
        }
    }


}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

运行结果:
在这里插入图片描述

欸,有点意思了,已经接近需要的结果了,看看之前本机的ifconfig的值:
在这里插入图片描述
起码蒙对了一个,不过enp3s0的还是没读出来。突破口就在这里。

下面查一查ifconfig下面的各个含义是什么。。我到现在都不明白这些含义,估计一天不弄清楚一天都没办法获得真正的物理地址了。
Linux网卡命名enp3s0说明
在这里插入图片描述

还有一篇:
linux下eth0 lo wlan0

在这里插入图片描述
在这里插入图片描述
通过阅读可以理解到,ifconfig在每个系统出来的名称还有格式估计都是有差别的。用字符串识别提取方式来获得mac地址估计。。。真的不行。mac地址在linux下面也是可以修改的。

而且:
en eth 都是本地网卡,有mac地址
lo是localhost,本机地址—这个不属于网卡吧,没有mac地址的吧?
wlan wl意思是无线网卡,也有mac地址。

我的是手提电脑,当然有无线网卡也有本地网卡。。额,这样就解释了:

enp3s0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether d8:c4:97:43:41:2f  txqueuelen 1000  (以太网)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 4067 bytes 537739 (537.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4067 bytes 537739 (537.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

wlp5s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.102 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::136b:f8d9:d35:b59 prefixlen 64 scopeid 0x20<link>
ether 68:ec:c5:c4:d1:96 txqueuelen 1000 (以太网)
RX packets 107772 bytes 149800655 (149.8 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 26297 bytes 4348455 (4.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

wlp5s0 无线网卡 有ip地址,ipv4: inet 192.168.0.102 ipv6: inet6 fe80::136b:f8d9:d35:b59 mac地址:68:ec:c5:c4:d1:96

而 enp3s0 内置网卡没有 ipv4,也没有ipv6地址,mac地址:d8:c4:97:43:41:2f

因为没有接网线啊,接的是无线。

lo 没有mac地址,ipv4为:127.0.0.1 ipv6为: ::1

网线网卡测试

为了求证上面结论,那么下面来做基本的试验,

笔记本用无线上网,没有插入网线

在这里插入图片描述

笔记本用禁用无线上网,插入网线

在这里插入图片描述

欸,wl不见了,en有ip地址了。。

笔记本用启用无线上网,插入网线

在这里插入图片描述
en,wl同时存在,都有ip地址。

而lo一直没有mac地址,ip地址一直是本地。就是说,java 获取本机ipmac时候,获取到本机lo的地址然后肯定没办法获得mac地址咯?

其他电脑ifconfig的表现

为了验证lo是不是不会有mac地址,特意查看其他人其他机器的表现,如下:
linux命令之ifconfig详细解释

在这里插入图片描述

估计lo真的是不会有mac地址了。。共性。所以现在的问题在于,如何遍历获取多个网卡的mac地址?

优化获取代码,不同情况进行试验

好了,现在来优化一下代码,在不同情况下运行程序进行测试:

代码如下:

package test;

import java.net.*;
import java.util.List;

public class MultiNetAddress {
/*
* @param args
* @throws UnknownHostException
* @throws SocketException
*/
public static void main(String[] args) throws UnknownHostException, SocketException {
System.out.println(“进行 multi net address 测试===》”);
java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while(en.hasMoreElements()){
NetworkInterface iface = en.nextElement();
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
//For each network interfaces iterate through each ip address
//For each network interfaces iterate through each ip address
for(InterfaceAddress addr : addrs) {
InetAddress ip = addr.getAddress();
System.out.println("Current IP address : " + ip.getHostAddress());

            NetworkInterface network = NetworkInterface.getByInetAddress(ip);

            if(network==null){
                System.out.println("真遗憾,系统无法获取"+ip+" 的network对象!!");
            }
            else{
                byte[] mac = network.getHardwareAddress();

                System.out.print("Current MAC address : ");

                StringBuilder sb = new StringBuilder();
                if(mac==null)
                {
                    System.out.println("真遗憾,系统无法获取"+ip+" 的mac地址");
                }
                else{
                    for (int i = 0; i &lt; mac.length; i++) {
                        sb.append(String.format("%02X%s", mac[i], (i &lt; mac.length - 1) ? "-" : ""));
                    }
                    System.out.println(sb.toString());
                }
            }

        }
    }


}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

情况一、不接网线,开启连接无线网络

ifconfig结果:
在这里插入图片描述

程序运行结果:
在这里插入图片描述

第二种情况,连接网线,开启并连接无线

ifconfig结果:
在这里插入图片描述

程序运行结果

在这里插入图片描述

第三种情况,连接网线,关闭无线

ifconfig结果

在这里插入图片描述

运行情况:

在这里插入图片描述

第四种情况,拔出网线,关闭无线

ifconfig结果:
在这里插入图片描述
运行结果:
在这里插入图片描述

获取mac地址的结论

在这几种情况下面

getNetworkInterfaces
  • 1

返回的分别的肯定有,lo—即localhost连接,
如果eth–内置网卡—有连接网线的话,那么就会包括etch,
如果wlan–无线—有连接的话,那么也会包括wlan。

getInterfaceAddresses
  • 1

会返回ipv4,以及ipv6的地址,对于lo这个networkinterface来说,会返回:
ipv6 0:0:0:0:0:0:0:1%lo 以及ipv4 127.0.0.1,遗憾的是:
lo的ipv6永远是连接不上的,network是null,而ipv4连接上了也是没有mac地址的,
基本上来说,linux下面是不能通过lo来获取mac的,windows下面不清楚
在这里插入图片描述

而其他两个,只要连接上了—eth以及wlan,只要连接上了就能获得mac地址:

Current IP address : fe80:0:0:0:136b:f8d9:d35:b59%wlp5s0
Current MAC address : 68-EC-C5-C4-D1-96
Current IP address : 192.168.0.102
Current MAC address : 68-EC-C5-C4-D1-96
Current IP address : fe80:0:0:0:d029:29c1:936c:64c9%enp3s0
Current MAC address : D8-C4-97-43-41-2F
Current IP address : 192.168.0.101
Current MAC address : D8-C4-97-43-41-2F
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

无论是ipv4还是ipv6

所以,现在心里面应该有底了,那就是,如何获取mac地址?

mac地址的获取通用代码

package test;

import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class MacTools {
/因为一台机器不一定只有一个网卡呀,所以返回的是数组是很合理的/
public static List<String> getMacList() throws Exception {
java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
StringBuilder sb = new StringBuilder();
ArrayList<String> tmpMacList=new ArrayList<>();
while(en.hasMoreElements()){
NetworkInterface iface = en.nextElement();
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
for(InterfaceAddress addr : addrs) {
InetAddress ip = addr.getAddress();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if(networknull){continue;}
byte[] mac = network.getHardwareAddress();
if(mac
null){continue;}
sb.delete( 0, sb.length() );
for (int i = 0; i < mac.length; i++) {sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? “-” : “”));}
tmpMacList.add(sb.toString());
} }
if(tmpMacList.size()<=0){return tmpMacList;}
/去重,别忘了同一个网卡的ipv4,ipv6得到的mac都是一样的,肯定有重复,下面这段代码是。。流式处理/
List<String> unique = tmpMacList.stream().distinct().collect(Collectors.toList());
return unique;
}
public static void main(String[] args) throws Exception {
System.out.println(“进行 multi net address 测试===》”);
List<String> macs=getMacList();
System.out.println(“本机的mac网卡的地址有:”+macs);

}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

运行结果:
在这里插入图片描述

后语

话说,真自豪。能够有理有据,各个情况都有考虑,将mac地址的获取清楚说出来的,恐怕不多。很多都是开局一段码,结果全靠蒙。
希望上面的东西能够帮到你、

                                </div>
版权声明:本文为m0_37641835原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37641835/article/details/103458168

智能推荐

Tornado day02

一,项目模板: Tornado的项目也可以像Django和flask一样,将功能细分为几个模块 1.1 _ _ init _ _.py 1.2 setting .py 1.3 urls .py 1.4 views .py 1.5 manage .py 将这个模板拷贝下来,以后创建新项目的时候可以直接拷贝一份,在此模板上修改使用 文件链接 链接:https://pan.baidu.com/s/11E...

PAT乙级 | 1095 解码PAT准考证 (25分)(做题过程+注意事项+运行超时解决方法)

PAT 准考证号由 4 部分组成: 第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级; 第 2~4 位是考场编号,范围从 101 到 999; 第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位; 最后 11~13 位是考生编号,范围从 000 到 999。 现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。 输入格式: 输入首先在一行中给出两个正整数 ...

谈谈Java异常

0 概述 对于java工程师来说,是经常和异常打交道的,本文主要来谈一谈java中的异常。 1 异常类的继承关系 从下图(说明:图中只是列出部分异常类)可以看出: 异常的基类为Throwable,主要分为两个分支,即Error体系和Exception体系。 Exception下面分为RuntimeException和非RuntimeException(如IOException) 2 几种异常的区别...

通过设立FatFS隐藏分区,实现系统文件和用户文件的隔离

嘛。。这是一个关于个人使用FatFS文件系统的 一点小的经验。 我知道大家都会百度和谷歌,关于文件系统有什么用,文件系统怎么移植上自己的平台,看看资料也就懂了,在这里不再详述( 打字太慢一分钟50-60字懒得写)。本系列默认已经可以将设备模拟成u盘,并且已经通过修改diskio.c,可以实现ff.c中的各项功能( 不能实现的自行面壁)。FatFS项目官网 http://elm-chan.org/f...

Mysql之锁与事务知识要点小结

Mysql之锁与事务 平时的业务中,顶多也就是写写简单的sql,连事务都用的少,对锁这一块的了解就更加欠缺了,之前一个大神分享了下mysql的事务隔离级别,感觉挺有意思的,正好发现一个很棒的博文,然后也收集了一些相关知识,正好来学习下,mysql中锁与事务的神秘面纱,主要内容包括 共享锁和排它锁的区别以及适合范围 mysql的表锁和行锁的区别 怎么判断一个sql是否执行了锁,执行的是表锁还是行锁 ...

猜你喜欢

响应式图片二 通过srcset实现

具体方法如下: srcset=”图片地址+空格+尺寸描述符,图片地址+空格+尺寸描述符,图片地址+空格+尺寸描述符….” 浏览器会当前浏览的环境进行感知,这个感知包括网速、界面分辨率、DPR(屏幕像素比)等等,然后在图片中选择一个进行加载。 实际上,在相同DPR下,浏览器会根据屏幕的分辨率加载图片,但是加载了大的图片后再缩小还是会使用大的图片。综合考虑的算法非...

Training_model(2)

已经清洗处理了两个数据文件: application_{train|test}.csv :客户详细信息 bureau.csv : 客户历史信用报告 下面对这两个数据中的特征进行合并,然后Light Gradient Boosting Machine训练模型,之前只用客户数据的预测评分结果是0.734,这次加入了客户信用报告信息 load data 新增加了客户历史信用记录 Build Model ...

微信小程序 页面跳转(传参跟不传参)

跳转页面传参 1.首先我的目录结构是这样的,并在 cinema.wxml 定义了一个点击事件 bindtap=‘indetai’ 2.然后在 cinema.js 的data里面定义了一个 score,并实现了 indetai 方法 3.在 detai.js 的 data 里面也定义一个 score ,再在 onLoad 函数里面接收传递过来的值 4.在页面上显示得到的值 这...

JavaSE 10(二维数组)

前言:      在经历了血雨腥风的地狱模式后本以为迎来了学习的平静,但二维数组又打破了这难得的平静!!!二维数组在java编程中同样也是很重要的知识点,因此在这里我将整理二维数组的知识点与重点,以及习题,便于自己的复习与巩固。 二维数组的声明与创建: 下面是声明二维数组的语法: 数据类型[][]数组名 : 数据类型数组名[][]; (允许这种方式 ,但并不推荐使用它...

深入理解 Linux 内存机制!| 技术头条

作者 | 阿文 责编 | 郭芮 作为一名Linux 系统运维工程,在日常管理 Linux 的时候,我们经常发现系统的空闲内存差不多总是被用完了。   通常,我们可以通过 top 和 free 查看内存使用情况:     执行 free:     为了更人性化地显示,我们可以加上 -h 选项:       可以看到我们的...