Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 查询ARP缓存以获取MAC ID_Java_Networking - Fatal编程技术网

Java 查询ARP缓存以获取MAC ID

Java 查询ARP缓存以获取MAC ID,java,networking,Java,Networking,我需要获取网络中主机的MAC ID。为此,如果我ping到该IP并查询ARP缓存ARP-a,我就能够获得MAC ID。我只是想知道是否可以获得任何API来查询ARP并获取MAC ID 另外,如果有更好的方法从IP地址获取MAC ID,请建议 附言:我在爪哇工作 谢谢。arp缓存在可用的SNMP数据集中作为标准提供。您可以使用编写一个简单的代理来查询此数据 e、 g.从命令行SNMP工具集 snmpwalk ${hostname} 1.3.6.1.2.1.4.22.1.2 (这个巨大的以句点分隔

我需要获取网络中主机的MAC ID。为此,如果我ping到该IP并查询ARP缓存
ARP-a
,我就能够获得MAC ID。我只是想知道是否可以获得任何API来查询ARP并获取MAC ID

另外,如果有更好的方法从IP地址获取MAC ID,请建议

附言:我在爪哇工作


谢谢。

arp缓存在可用的SNMP数据集中作为标准提供。您可以使用编写一个简单的代理来查询此数据

e、 g.从命令行SNMP工具集

snmpwalk ${hostname} 1.3.6.1.2.1.4.22.1.2
(这个巨大的以句点分隔的字符串是SNMP术语中ARP缓存的OID或标识符。这适用于所有SNMP实现)

ARP是将IP地址映射到MAC地址的方法。IP堆栈就是这样做的

我不确定是否有一种可移植的方式来获取这些信息,因为它通常只对内核开发人员和系统管理员重要


通过大量的网络搜索,似乎可以使用SNMP获取路由器的ARP表,但我没有找到很多关于如何实现这一点的具体信息。不过,我确实找到了一个免费的SNMP Java库。有些拼写可能是有成效的。

< P>这在java上下文中可能无法解决(因为它是平台无关的),但是你也应该考虑是否可以通过系统服务获得MAC地址。有些情况下,您可能无法通过ARP可靠地找到MAC地址,这取决于您需要MAC地址的原因。

Java无法直接查询网络中主机的MAC地址,因为这是由Java的套接字库抽象出来的

从某种意义上说,这是有道理的,因为主机的MAC地址实际上说明的很少。没有主机的MAC地址这样的东西

  • 许多主机将有几个NIC,所有NIC都有一个单独的MAC地址,它们可以通过该地址连接到网络。我现在使用的电脑有有线以太网适配器、WiFi适配器和Firewire适配器,它们都有自己的MAC地址。这意味着主机没有确定的MAC地址
  • 如果主机位于不同的子网中,ARP将实际为您提供数据包通过的最后一个路由器的MAC地址,而不是您正在扫描的主机的MAC地址
把这两个问题放在一起,这意味着一个主机可能有许多不同的MAC地址(如果它有多个NIC),而一个MAC地址可能代表许多不同的主机(如果流量通过路由器)

假设您知道所有这些,并且仍然需要获取主机的MAC地址,那么在Java中实现这一点的唯一方法是“使用本机”:

  • 运行您的程序的客户端本机:
    • 您可以启动ARP命令行工具并解析其输出
    • 您可以使用某种JNI调用。不过我对JNI不太熟悉,所以我不能帮你
    • 编写一个单独的小型本机应用程序,您可以通过Telnet或类似协议从Java访问该应用程序,该应用程序将为您运行ARP命令
  • 要扫描的主机的本机:
    • 您可以使用SNMP,正如对此线程的一些其他答案所建议的那样。我遵从这些答案,为你做这件事。SNMP是一个很好的协议,但请注意,SNMP的OID可以依赖于平台,也可以依赖于供应商。适用于Windows的OID并不总是适用于Linux,反之亦然
    • 如果您知道您的主机运行Windows,则可以使用。该类保存您想要的信息,但请注意,这将返回所有主机NIC,甚至是Windows组成的主机NIC。此外,它还需要您正在扫描的主机的管理员凭据。Google将告诉您如何从Java连接到WMI
    • 如果您知道您的主机运行的是OSX,那么您可能能够通过SSH连接到机器中,并解析
      system\u profile
      命令的输出
    • 对于Linux,可能存在类似于OSX的
      system\u profile
      的工具
您可以通过以下方式获得自己的MAC地址:

Enumeration<NetworkInterface> it = NetworkInterface.getNetworkInterfaces();
while ( it.hasMoreElements() ) {
    byte[] macAddress = it.nextElement().getHardwareAddress();
}
Enumeration it=NetworkInterface.getNetworkInterfaces();
while(it.hasMoreElements()){
字节[]macAddress=it.nextElement().getHardwareAddress();
}
绝对没有办法通过vanilla java获得另一台主机的MAC地址。您必须使用进程执行或本机库来执行


如果你控制其他机器,你可以让他们查询自己的MAC,然后通过TCP/IP通道发送回去,但我猜这不是你想要的。有关更多详细信息,请参阅jqno的答案。

正如其他人所说,ARP是一条出路。以下是基于jqnos的第二个建议的实现

需要两个图书馆:

  • 用于网络流量捕获的系统库:
    • 基于Linux的:libpcap可从
    • Windows:winpcap可从
  • jpcap java库可从获得,它通过JNI向第一个库提供高级接口

    public class GetMACAddress {
    
    /**
     * 
     * @param ip address containing an IP
     * @return MAC-Address as formatted String
     * @throws IOException
     * @throws IllegalArgumentException
     */
    public static String getMACAdressByIp(Inet4Address ip) throws IOException, IllegalArgumentException {
    
        byte[] mac = GetMACAddress.getMACAddressByARP(ip);
    
        StringBuilder formattedMac = new StringBuilder();
        boolean first = true;
        for (byte b : mac) {
            if (first) {
                first = false;
            } else {
                formattedMac.append(":");
            }
            String hexStr = Integer.toHexString(b & 0xff);
            if (hexStr.length() == 1) {
                formattedMac.append("0");
            }
            formattedMac.append(hexStr);
        }
    
        return formattedMac.toString();
    }
    
    private static byte[] getMACAddressByARP(Inet4Address ip) throws IOException, IllegalArgumentException {
    
        NetworkInterface networkDevice = getNetworkDeviceByTargetIP(ip);
    
        JpcapCaptor captor = JpcapCaptor.openDevice(networkDevice, 2000, false, 3000);
        captor.setFilter("arp", true);
        JpcapSender sender = captor.getJpcapSenderInstance();
    
        InetAddress srcip = null;
        for (NetworkInterfaceAddress addr : networkDevice.addresses)
            if (addr.address instanceof Inet4Address) {
                srcip = addr.address;
                break;
            }
    
        byte[] broadcast = new byte[] { (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255 };
        ARPPacket arp = new ARPPacket();
        arp.hardtype = ARPPacket.HARDTYPE_ETHER;
        arp.prototype = ARPPacket.PROTOTYPE_IP;
        arp.operation = ARPPacket.ARP_REQUEST;
        arp.hlen = 6;
        arp.plen = 4;
        arp.sender_hardaddr = networkDevice.mac_address;
        arp.sender_protoaddr = srcip.getAddress();
        arp.target_hardaddr = broadcast;
        arp.target_protoaddr = ip.getAddress();
    
        EthernetPacket ether = new EthernetPacket();
        ether.frametype = EthernetPacket.ETHERTYPE_ARP;
        ether.src_mac = networkDevice.mac_address;
        ether.dst_mac = broadcast;
        arp.datalink = ether;
    
        sender.sendPacket(arp);
    
        while (true) {
            ARPPacket p = (ARPPacket) captor.getPacket();
            if (p == null) {
                throw new IllegalArgumentException(ip + " is not a local address");
            }
            if (Arrays.equals(p.target_protoaddr, srcip.getAddress())) {
                return p.sender_hardaddr;
            }
        }
    }
    
    private static NetworkInterface getNetworkDeviceByTargetIP(Inet4Address ip) throws IllegalArgumentException {
    
        NetworkInterface networkDevice = null;
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
    
        loop: for (NetworkInterface device : devices) {
            for (NetworkInterfaceAddress addr : device.addresses) {
                if (!(addr.address instanceof Inet4Address)) {
                    continue;
                }
                byte[] bip = ip.getAddress();
                byte[] subnet = addr.subnet.getAddress();
                byte[] bif = addr.address.getAddress();
                for (int i = 0; i < 4; i++) {
                    bip[i] = (byte) (bip[i] & subnet[i]);
                    bif[i] = (byte) (bif[i] & subnet[i]);
                }
                if (Arrays.equals(bip, bif)) {
                    networkDevice = device;
                    break loop;
                }
            }
        }
    
        if (networkDevice == null) {
            throw new IllegalArgumentException(ip + " is not a local address");
        }
    
        return networkDevice;
    }
    
    }
    
    公共类GetMACAddress{
    /**
    * 
    *@param包含ip地址的ip地址
    *@以格式化字符串形式返回MAC地址
    *@抛出异常
    *@galargumentException
    */
    公共静态字符串GetMacAddressByIP(Inet4Address ip)引发IOException、IllegalArgumentException{
    字节[]mac=GetMACAddress.getMACAddressByARP(ip);
    StringBuilder formattedMac=新StringBuilder();
    布尔值优先=真;
    用于(字节b:mac){
    如果(第一){
    第一个=假;
    }否则{
    formattedMac.append(“:”);
    }
    字符串hextr=Integer.tohextstring(b&0xff);
    如果(hexStr.length()==1){
    formattedMac.append(“0”);
    }
    formattedMac.append(hexStr);
    }
    返回formattedMac.toString();
    }
    私有静态字节[]getMACAddressByARP(Inet4Address ip)引发IOException,非法
    
    private static final String ARP_GET_IP_HW = "arp -a";
    
    public String getARPTable(String cmd) throws IOException {
               Scanner s = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
                    return s.hasNext() ? s.next() : "";
        }
    
    System.out.println(getARPTable(ARP_GET_IP_HW ));
    
     public static String getARPTable(String ip) throws IOException {
            String systemInput = "";
    //to renew the system table before querying 
            Runtime.getRuntime().exec("arp -a");
            Scanner s = new Scanner(Runtime.getRuntime().exec("arp -a " + ip).getInputStream()).useDelimiter("\\A");
            systemInput = s.next();
            String mac = "";
            Pattern pattern = Pattern.compile("\\s{0,}([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})");
            Matcher matcher = pattern.matcher(systemInput);
            if (matcher.find()) {
                mac = mac + matcher.group().replaceAll("\\s", "");
            } else {
                System.out.println("No string found");
            }
            return mac;
        }
    
        public static void main(String[] args) throws IOException {
    
            System.out.println(getARPTable("192.168.1.23"));
            // prints 74-d4-35-76-11-ef
    
        }