前言
原本以为这功能调用一个api就完事了,然而,查了一下没那么简单,网上查的资料实在忍不住要拿出来说说,估计真的都没有试过其他环境,而且,估计连背后的原理都没了解就用了。。
下面先说说找到的几份资料:
ps:本机相关ip信息:
第一篇参考
点评:实际运行效果如下:
空指针啊。。。那么我们如果换个ip来试试?
第二篇参考
看看代码:
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);
}
}
一运行:
还是不行。。里面几行代码我有点在意:
process = Runtime.getRuntime().exec("ifconfig enp4s0");
index = line.toLowerCase().indexOf("硬件地址");
调用命令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());
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 ...
好了,根据以上回答及代码,补充完整,然后查看结果
单地址:
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 < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
System.out.println(sb.toString());
}
}
运行结果:
不行,还是出错了。。
多地址的:
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 < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
System.out.println(sb.toString());
}
}
}
}
运行结果:
欸,有点意思了,已经接近需要的结果了,看看之前本机的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
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 < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
System.out.println(sb.toString());
}
}
}
}
}
}
情况一、不接网线,开启连接无线网络
ifconfig结果:
程序运行结果:
第二种情况,连接网线,开启并连接无线
ifconfig结果:
程序运行结果
第三种情况,连接网线,关闭无线
ifconfig结果
运行情况:
第四种情况,拔出网线,关闭无线
ifconfig结果:
运行结果:
获取mac地址的结论
在这几种情况下面
getNetworkInterfaces
返回的分别的肯定有,lo—即localhost连接,
如果eth–内置网卡—有连接网线的话,那么就会包括etch,
如果wlan–无线—有连接的话,那么也会包括wlan。
而
getInterfaceAddresses
会返回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
无论是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(network==null){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);
}
}
运行结果:
后语
话说,真自豪。能够有理有据,各个情况都有考虑,将mac地址的获取清楚说出来的,恐怕不多。很多都是开局一段码,结果全靠蒙。
希望上面的东西能够帮到你、