我需要獲取網絡中主機的MAC ID。爲此,如果我ping到該IP並查詢ARP緩存arp -a
,我能夠獲得MAC ID。我只是想知道我是否可以獲取任何API來查詢ARP並獲取MAC ID。查詢ARP緩存以獲取MAC ID
此外,如果有更好的方法從IP地址獲取MAC ID,請提出建議。
P.S:我正在使用JAVA。
謝謝。
我需要獲取網絡中主機的MAC ID。爲此,如果我ping到該IP並查詢ARP緩存arp -a
,我能夠獲得MAC ID。我只是想知道我是否可以獲取任何API來查詢ARP並獲取MAC ID。查詢ARP緩存以獲取MAC ID
此外,如果有更好的方法從IP地址獲取MAC ID,請提出建議。
P.S:我正在使用JAVA。
謝謝。
Java沒有提供直接的方法來查詢網絡中主機的MAC地址,因爲它被Java的套接字庫抽象掉了。
從某種意義上說,這是有道理的,因爲主機的MAC地址實際上說的很少。沒有主機的「MAC」地址。
把這兩個問題一起,這意味着一臺主機可以具有許多不同的MAC地址(如果它有多個NIC),以及一個MAC地址可代表許多不同的主機(如果流量通過路由器)。
假設你知道這一切,你仍然需要獲得主機的MAC地址,這樣做在Java中的唯一途徑是通過「去本土化」:
system_profile
命令的輸出。system_profile
的工具。arp緩存在可用的SNMP數據集中作爲標準提供。您可以使用SNMP4J編寫一個簡單的代理來查詢此數據。
例如從命令行SNMP工具集
snmpwalk ${hostname} 1.3.6.1.2.1.4.22.1.2
(即巨大週期分隔的字符串是OID,或標識符,在SNMP術語ARP高速緩存的。這將所有SNMP實現工作)
ARP是將IP地址映射到MAC地址的方式爲。這就是IP堆棧的作用。
我不確定是否有可移植的方式來獲取該信息,因爲它通常只對內核開發人員和系統管理員很重要。
從大量的網絡搜索中,它可能使用SNMP獲取路由器的ARP表,但我沒有找到關於如何去做的大量具體信息。我確實找到了一個免費的用於SNMP here的Java庫。通過那裏的一些探索可能證明是有成效的。
這可能無法在Java環境下解決(因爲它與平臺無關),但是您還應該考慮是否可以通過系統服務獲取MAC地址。有可能你無法通過ARP可靠地找到MAC地址,這取決於你爲什麼需要MAC地址。
最好的情況是,ARP表最多有**這個**機器聽說過的**和MAC最近的**關聯。如果您的遠程計算機更改IP,但還沒有將任何網絡流量發送到此計算機(或廣播)的理由,那麼此計算機上的ARP表已過時,只是還不知道它。 – 2015-01-29 20:54:04
你可以通過自己 MAC地址:
Enumeration<NetworkInterface> it = NetworkInterface.getNetworkInterfaces();
while (it.hasMoreElements()) {
byte[] macAddress = it.nextElement().getHardwareAddress();
}
肯定是有沒有辦法,你可以通過java的香草拿到另一臺主機的MAC地址。您必須使用Process執行或本機庫來執行此操作。
如果你控制其他機器,你可以讓他們查詢自己的MAC並通過TCP/IP通道發送回去,但我猜這不是你想要的。有關更多詳細信息,請參閱jqno的答案。
問題是:「獲取我的網絡中主機的MAC ID」,即不是您自己的。恐怕我不得不冷靜地回答這個問題。 – 2014-11-17 08:34:52
正如其他人所說,ARP是要走的路。以下是基於this example on GitSpot的jqnos第二個建議的實現。
兩個庫要求:對網絡流量捕捉
可從the jpcap sourceforge site獲得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;
}
}
h級接口的第一個庫還有一個更簡單的方法:
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));
,你會得到eintire ARP表中的IP和硬件上排序的每一行。
然後,您可以將表拆分爲單獨的String行,並在每行上使用正則表達式來匹配HW和IP地址。你完成了。
通過啓發greenspand答案我想出了這個代碼將使用查詢使用指定的IP IP和CMD命令爲MAC地址。
注意,在此代碼的工作視窗,我相信它可以用很少的修改上Linux的工作了。
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
}
請注意,ARP緩存的SNMP OID與供應商無關。它不是企業MIB的一部分。 – 2009-10-01 16:27:40