Java: 获取MAC网络地址

    技术2024-11-29  15

    Java: 获取MAC网络地址

    0. 背景

    最近由于课程设计,需要使用MAC物理地址作为软件注册码的唯一标识,故成此博客!

    从各个网络适配器的作用 → \rightarrow 确定哪一个MAC地址作为唯一标识。在此记录,与诸君分享。

    1. 首先打开cmd → \rightarrow ipconfig/all ,查看所有MAC地址:

    2. 博主的ipconfig存在8个网络适配器,故而存在 8 个MAC物理地址。

    其中每个网络适配器的含义如下:

    Mac网卡地址解析:

    Sangfor SSL VPN CS Support System VNIC

    EasyConnect,远程连接VPN应用产生的虚拟网卡。

    具备Mac网卡地址

    Realtek PCIe GBE Family Controller

    realtek公司生产的PCIe接口的千兆以太网家用控制器,即 有线网卡。

    具备Mac网卡地址

    VirtualBox Host-Only Ethernet Adapter

    用于对 虚拟机 进行 通信 的适配器。

    具备Mac网卡地址

    Npcap Loopback Adapter

    虚拟网卡,不涉及硬件,它被用于在网络连接不可用时,作为测试虚拟网络环境的工具。

    此外,如果 网络适配器(network adapter) / 网络适配器驱动程序(network adapter driver) 发生冲突,则必须使用 Loopback适配器。

    Java中的NetworkInterface中定义:

    loopback interface that only supports communication between entities on this machine.

    本地环回测试的MAC地址,全球所有的计算机相同!!!

    具备Mac网卡地址

    Microsoft Wi-Fi Direct Virtual Adapter

    虚拟网卡,使用PC的便携式 热点(hotspot) 共享PC的互联网连接。

    当PC连接无线网,并开启移动热点后,PC会向外发射信号给其他终端,其他终端检测到PC发射出的网络信号,并且可以连接PC发出的无线网络!

    多用于移动设备投屏PC。

    具备Mac网卡地址

    Microsoft Wi-Fi Direct Virtual Adapter #2

    Virual Wi-Fi是一种虚拟化网络适配器的技术,一旦被虚拟化,那么,即可将 1 个物理无线适配器转换为 2 个虚拟适配器。

    具备Mac网卡地址

    Intel® Dual Band Wireless-AC 3168

    无线网卡。

    具备Mac网卡地址

    Bluetooth Device (Personal Area Network)

    一种允许创建一个以太网(Ethernet network) 的技术,其允许计算机与移动设备等进行连接。

    局域网(PAN)网卡。

    具备Mac网卡地址

    3. 了解了各网络适配器的MAC物理地址后,我们可以更加 自信 的编程了!

    因为MAC地址数量很多,而虚拟网卡的MAC地址又可以后期修改,只有 无线网卡(Intel® Dual Band Wireless-AC 3168) 和 有限网卡(Realtek PCIe GBE Family Controller) 的MAC物理地址始终无法被改变并且绝大多数电脑都具备这两种网卡;

    故,此处选择 无线网卡(Intel® Dual Band Wireless-AC 3168) 的MAC地址作为软件注册码的唯一标识。

    ps:这里说明下,为什么不选择 Npcap Loopback Adapter 的MAC地址作为唯一标识的原因:

    因为,全球所有的计算机的 Loopback Adapter 的 MAC地址 都为 02-00-4C-4F-4F-50;

    而且,因为 MAC地址 位于计算机网络OSI参考模型的 数据链路层 中,其 作用 是 在网络中唯一标示一个网卡,并由此标识唯一计算机,这样,该计算机才能准确的与其他计算机通信;

    然而, Loopback 的 作用 是用于 本地环回测试,不需要与其他计算机通信,因此其物理地址全球性一致,不具有唯一标识性。

    ps: 感兴趣的小朋友可以cmd → \rightarrow ipconfig/all 看下,是不是你的 Loopback 的MAC地址 是否与博主一致!😁

    获取MAC地址程序如下:

    import sun.encryption.constants.Constants; import sun.encryption.domain.Network; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.List; import java.util.Enumeration; public class NetworkUtil { /** * 一台机器可能存在多个网卡, 故返回数组 * 网络接口地址(NetworkInterface) ----> 接口地址(InterfaceAddress) ----> IP地址(InetAddress) * ----> 网络接口地址(NetworkInterface) * @return * @throws Exception */ public static List<Network> getMacAddresses() throws Exception { // 获取机器上的所有网络接口, 返回结果至少包含一项(即, loopback本地环回测试) // getNetworkInterfaces() + getInetAddresses()可以获取到所有IP地址 Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); StringBuilder sb = new StringBuilder(); ArrayList<String> networkNames = new ArrayList<String>(); // 保存mac地址列表 ArrayList<Network> macList = new ArrayList<Network>(); // 使用标签, 跳出多重循环 here: while (en.hasMoreElements()) { NetworkInterface iface = en.nextElement(); // 获取对应网络接口的所有接口地址(InterfaceAddress) List<InterfaceAddress> addrs = iface.getInterfaceAddresses(); for (InterfaceAddress addr : addrs) { // InetAddress: Internet Protocol (IP) address: IP地址 // 返回网络接口地址对应的IP地址 InetAddress ip = addr.getAddress(); // 由IP地址获取网络接口(NetworkInterface) // 方便方法搜索到绑定到其的具体IP地址的网络接口(NetworkInterface) NetworkInterface networkInterface = NetworkInterface.getByInetAddress(ip); // 若为空, 跳过 if (networkInterface == null) { continue; } // 获取以太网等名称, 如:eth0, eth1, wlan1 String name = networkInterface.getName(); // 获取描述 String displayName = networkInterface.getDisplayName(); // 当网络接口有权限连接, 并且其具有MAC地址时, 返回二进制MAC硬件地址 byte[] mac = networkInterface.getHardwareAddress(); // 是否为虚拟网络接口 boolean virtual = networkInterface.isVirtual(); // 网络接口是否启动 boolean up = networkInterface.isUp(); if (mac == null) { continue; } // 清空StringBuffer中的内容 sb.delete(0, sb.length()); // 转换MAC地址格式 for (int i = 0; i < mac.length; i++) { sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); } Network network = new Network(); // 若网络接口首次出现, 避免返回结果重复 if (!networkNames.contains(name)) { networkNames.add(name); network.setName(name); network.setDisplayName(displayName); network.setMac(sb.toString()); network.setVirtual(virtual); network.setUp(up); macList.add(network); } // 若找到, 跳出 if (networkNames.contains(Constants.WIRELESS)) { break here; } } } return macList; } // 根据字符串"wireless"找到对应mac地址 // 方法有效的条件是: PC机具有无线网卡 // linux再议 public static String getWirelessMacAddress() throws Exception { List<Network> macs = getMacAddresses(); for (Network mac: macs) { if (mac.getDisplayName().toLowerCase().contains(Constants.WIRELESS)) { return mac.getMac(); } } return null; } public static void main(String[] args) throws Exception { String wirelessMac = getWirelessMacAddress(); System.out.println(wirelessMac); } }
    Processed: 0.022, SQL: 9