【问题标题】:Get MAC address on local machine with Java使用 Java 在本地机器上获取 MAC 地址
【发布时间】:2011-05-28 20:27:00
【问题描述】:

我可以使用

ip = InetAddress.getLocalHost();
NetworkInterface.getByInetAddress(ip);

获取mac地址,但是如果我在离线机器上使用这个代码就不行了。

那么,如何获取 Mac 地址?

【问题讨论】:

  • 从技术上讲,你应该把离线机器当作它没有网卡。你如何处理后一种情况?
  • 为什么您的程序需要这些信息?它对最终用户有什么好处?
  • 如果机器有多个怎么办?您是否知道用户可以更改 MAC 地址?在 Java 中,除了尝试将 MAC 地址用作机器标识符之外,您无能为力,但这还不够。
  • 谢谢,我尝试用它作为机器标识符,那么在java中识别机器的正确方法是什么?
  • @EJP 你对此有何建议?

标签: java sockets mac-address


【解决方案1】:

对于 Java 6+,您可以使用 NetworkInterface.getHardwareAddress

请记住,计算机可以没有网卡,尤其是嵌入式或虚拟计算机。它也可以有多个。您可以使用NetworkInterface.getNetworkInterfaces() 获取所有网卡的列表。

【讨论】:

  • 我遇到了一个问题,我在某些计算机上只有一个截断的 4 字节 MAC 地址。我设法通过包含 -Djava.net.preferIPv4Stack=true 作为 java 的启动参数来解决这个问题
【解决方案2】:

有了我在这里找到的所有可能的解决方案和其他回复,然后我将贡献我的解决方案。您需要使用包含“ip”或“mac”的字符串指定参数,具体取决于您需要检查的内容。如果计算机没有接口,那么它会返回一个包含null的String,否则将返回一个包含你所要求的(IP地址或mac)的String。

使用方法:

System.out.println("Ip: " + GetNetworkAddress.GetAddress("ip"));
System.out.println("Mac: " + GetNetworkAddress.GetAddress("mac"));

结果(如果电脑有网卡):

Ip: 192.168.0.10 
Mac: 0D-73-ED-0A-27-44

结果(如果电脑没有网卡):

Ip: null
Mac: null

代码如下:

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

public class GetNetworkAddress {

    public static String GetAddress(String addressType) {
        String address = "";
        InetAddress lanIp = null;
        try {

            String ipAddress = null;
            Enumeration<NetworkInterface> net = null;
            net = NetworkInterface.getNetworkInterfaces();

            while (net.hasMoreElements()) {
                NetworkInterface element = net.nextElement();
                Enumeration<InetAddress> addresses = element.getInetAddresses();

                while (addresses.hasMoreElements() && element.getHardwareAddress().length > 0 && !isVMMac(element.getHardwareAddress())) {
                    InetAddress ip = addresses.nextElement();
                    if (ip instanceof Inet4Address) {

                        if (ip.isSiteLocalAddress()) {
                            ipAddress = ip.getHostAddress();
                            lanIp = InetAddress.getByName(ipAddress);
                        }

                    }

                }
            }

            if (lanIp == null)
                return null;

            if (addressType.equals("ip")) {

                address = lanIp.toString().replaceAll("^/+", "");

            } else if (addressType.equals("mac")) {

                address = getMacAddress(lanIp);

            } else {

                throw new Exception("Specify \"ip\" or \"mac\"");

            }

        } catch (UnknownHostException ex) {

            ex.printStackTrace();

        } catch (SocketException ex) {

            ex.printStackTrace();

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return address;

    }

    private static String getMacAddress(InetAddress ip) {
        String address = null;
        try {

            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
            byte[] mac = network.getHardwareAddress();

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

        } catch (SocketException ex) {

            ex.printStackTrace();

        }

        return address;
    }

    private static boolean isVMMac(byte[] mac) {
        if(null == mac) return false;
        byte invalidMacs[][] = {
                {0x00, 0x05, 0x69},             //VMWare
                {0x00, 0x1C, 0x14},             //VMWare
                {0x00, 0x0C, 0x29},             //VMWare
                {0x00, 0x50, 0x56},             //VMWare
                {0x08, 0x00, 0x27},             //Virtualbox
                {0x0A, 0x00, 0x27},             //Virtualbox
                {0x00, 0x03, (byte)0xFF},       //Virtual-PC
                {0x00, 0x15, 0x5D}              //Hyper-V
        };

        for (byte[] invalid: invalidMacs){
            if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) return true;
        }

        return false;
    }

}

2017 年 2 月 5 日更新:感谢 @mateuscb 在帖子 How to Determine Internet Network Interface in Java 上,不幸的是,他之前没有在该帖子上获得任何支持,但他为这次更新做出了贡献。

该方法已改进为跳过虚拟机网卡(最流行的VM软件)

【讨论】:

  • 如果在if (invalid[0] == mac[0] &amp;&amp; invalid[1] == mac[1] &amp;&amp; invalid[2] == mac[2]) return true; 出现ArrayIndexOutOfBounds 异常,我该怎么办?
  • @Sumit 检查两个数组“invalid”和“mac”中的项目数,因为其中一个或两个都少于三个
  • 所以我在stackoverflow.com/a/16449379/3169868 找到了另一段代码,它显示第一个 MAC 地址为空白,其余 3 个(包括 VM)。可以修改此代码以处理此问题吗?
  • @Sumit 尝试将这一行 while (addresses.hasMoreElements() &amp;&amp; !isVMMac(element.getHardwareAddress())) { 替换为 while (addresses.hasMoreElements() &amp;&amp; element.getHardwareAddress().length &gt; 0 &amp;&amp; !isVMMac(element.getHardwareAddress())) {
  • 谢谢,现在工作正常!也许您也可以考虑更新答案中的示例代码。
【解决方案3】:

对于离线的电脑,一般不会分配IP,因为DHCP被广泛使用...

对于标题中的问题: NetworkInterface.getHardwareAddress()

【讨论】:

    【解决方案4】:

    另一种方法是通过本机代码执行使用操作系统命令“getmac”。

        Process p = Runtime.getRuntime().exec("getmac /fo csv /nh");
        java.io.BufferedReader in = new java.io.BufferedReader(new  java.io.InputStreamReader(p.getInputStream()));
        String line;
        line = in.readLine();        
        String[] result = line.split(",");
    
        System.out.println(result[0].replace('"', ' ').trim());
    

    【讨论】:

    • getmac 仅在 Windows 上可用。但不是在 Ubuntu 13.10(也不是 apt-get)和 Android 4.2 上。
    【解决方案5】:

    试试这个:

    final NetworkInterface netInf = NetworkInterface.getNetworkInterfaces().nextElement();
    final byte[] mac = netInf.getHardwareAddress();
    final StringBuilder sb = new StringBuilder();
    for (int i = 0; i < mac.length; i++) {
            sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));        
    }
    log.info("Mac addr: {}", sb.toString());
    

    【讨论】:

    • 有些异常你应该捕捉到。
    • 对我来说 getHardwareAddress 为空。知道为什么吗?我只在笔记本电脑上运行。没有 VM 或任何 aws 或 azure 实例
    • getInetAddresses().nextElement() 给出 /127.0.0.1
    【解决方案6】:

    here清理代码:

    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    
    public class HardwareAddress
    {
        public static String getMacAddress() throws UnknownHostException,
                SocketException
        {
            InetAddress ipAddress = InetAddress.getLocalHost();
            NetworkInterface networkInterface = NetworkInterface
                    .getByInetAddress(ipAddress);
            byte[] macAddressBytes = networkInterface.getHardwareAddress();
            StringBuilder macAddressBuilder = new StringBuilder();
    
            for (int macAddressByteIndex = 0; macAddressByteIndex < macAddressBytes.length; macAddressByteIndex++)
            {
                String macAddressHexByte = String.format("%02X",
                        macAddressBytes[macAddressByteIndex]);
                macAddressBuilder.append(macAddressHexByte);
    
                if (macAddressByteIndex != macAddressBytes.length - 1)
                {
                    macAddressBuilder.append(":");
                }
            }
    
            return macAddressBuilder.toString();
        }
    }
    

    【讨论】:

      【解决方案7】:

      介质访问控制地址(MAC address

      设备的 MAC 地址是分配给网络接口控制器 (NIC) 的唯一标识符。对于网段内的通信,它被用作大多数 IEEE 802 网络技术的网络地址,包括以太网、Wi-Fi 和蓝牙。在开放系统互连 (OSI) 模型中,MAC 地址用于数据链路层的介质访问控制协议子层。

      MAC 地址通常由网络接口​​卡的制造商分配。每个都存储在硬件中,例如卡的只读存储器或通过固件机制。

      使用以下函数getPhysicalAddress()获取MAC地址列表:

      static String format = "%02X"; // To get 2 char output.
      private static String[] getPhysicalAddress() throws Exception{
          try {
              // DHCP Enabled - InterfaceMetric
              Set<String> macs = new LinkedHashSet<String>();
      
              Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
              while( nis.hasMoreElements() ) {
                  NetworkInterface ni = nis.nextElement();
                  byte mac [] = ni.getHardwareAddress(); // Physical Address (MAC - Medium Access Control)
                  if( mac != null ) {
                      final StringBuilder macAddress = new StringBuilder();
                      for (int i = 0; i < mac.length; i++) {
                          macAddress.append(String.format("%s"+format, (i == 0) ? "" : ":", mac[i]) );
                          //macAddress.append(String.format(format+"%s", mac[i], (i < mac.length - 1) ? ":" : ""));
                      }
                      System.out.println(macAddress.toString());
                      macs.add( macAddress.toString() );
                  }
              }
              return macs.toArray( new String[0] );
          } catch( Exception ex ) {
              System.err.println( "Exception:: " + ex.getMessage() );
              ex.printStackTrace();
          }
          return new String[0];
      }
      
      public static void main(String[] args) throws Exception {
          InetAddress localHost = InetAddress.getLocalHost();
          System.out.println("Host/System Name : "+ localHost.getHostName());
          System.out.println("Host IP Address  : "+ localHost.getHostAddress());
      
          String macs2 [] = getPhysicalAddress();
          for( String mac : macs2 )
              System.err.println( "MacAddresses = " + mac );
      }
      

      上述函数作为ipconfig/all|find "Physical Address" &gt;&gt;MV-mac.txt工作。

      D:\>ipconfig /all|find "Physical Address"
         Physical Address. . . . . . . . . : 94-57-A6-00-0C-BB
         Physical Address. . . . . . . . . : 01-FF-60-93-0B-88
         Physical Address. . . . . . . . . : 62-B8-9A-2B-F3-87
         Physical Address. . . . . . . . . : 60-B8-9A-2B-F3-87
         Physical Address. . . . . . . . . : 60-B8-9A-2B-F3-87
      

      IEEE divides the OSI data link layer 分成两个独立的子层:

      • 逻辑链路控制 (LLC):向上过渡到网络层
      • MAC:向下过渡到物理层Image ref

      getmac

      返回本地或跨网络的每台计算机中所有网卡的媒体访问控制 (MAC) 地址和与每个地址关联的网络协议列表。

      D:\>getmac /fo csv /nh
      

      NET START 命令

      D:\>netsh interface ipv4 show addresses
      

      【讨论】:

        【解决方案8】:

        科特林:

        NetworkInterface.getNetworkInterfaces()
            .asSequence()
            .mapNotNull { ni ->
                ni.hardwareAddress?.joinToString(separator = "-") {
                    "%02X".format(it)
                }
            }.toList()
        

        【讨论】:

          【解决方案9】:
          public static void main(String[] args){
          
                  InetAddress ip;
                  try {
          
                      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());
          
                  } catch (Exception e) {
          
                      e.printStackTrace();
          
                  }
          
                 }
          

          输出:

          Current IP address : 192.168.21.60
          Current MAC address : 70-5A-0F-3C-84-F2
          

          【讨论】:

          • 这正是原帖所说的适用于离线计算机。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-29
          • 2022-10-14
          • 2014-07-12
          • 1970-01-01
          相关资源
          最近更新 更多