方案一:本地 MAC(JDK 1.6+ NetworkInterface)
public static String getLocalMac() throws SocketException {
InetAddress local = InetAddress.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(local);
byte[] mac = ni.getHardwareAddress();
StringBuilder sb = new StringBuilder();
for (int i=0; i0) sb.append("-");
String s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length()==1 ? "0"+s : s);
}
return sb.toString().toUpperCase();
}
方案二:遠程 IP 獲取 MAC(Windows nbtstat)
public static String getRemoteMacWin(String ip) throws IOException {
Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.indexOf("MAC") > 1) {
return line.substring(line.indexOf("MAC")+9).trim();
}
}
return null;
}
方案三:ARP 協議解析(跨平台,支持外網)
public static String getMacByArp(String ip) throws IOException, InterruptedException {
// 先 ping 刷新 ARP 緩存
Runtime.getRuntime().exec("ping " + ip).waitFor();
// 讀取 ARP 表
Process p = Runtime.getRuntime().exec("arp -n"); // Linux: arp -a
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.contains(ip)) {
// 正則提取 MAC
Pattern pat = Pattern.compile("(([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2})");
Matcher m = pat.matcher(line);
if (m.find()) return m.group(1).toUpperCase();
}
}
return null;
}
方案四:ipconfig/all 解析(Windows 本地)
public static String getMacByIpconfig() throws IOException {
Process p = Runtime.getRuntime().exec("cmd.exe /c ipconfig/all");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.indexOf("Physical Address") > 0) {
return line.substring(line.indexOf("Physical Address")+36).trim();
}
}
return null;
}
綜合工具類:自動選擇最佳方案
public class MacUtil {
public static String getMac(String ip) {
String mac = getMacByArp(ip); // 優先 ARP
if (mac == null) mac = getRemoteMacWin(ip); // Windows 回退
if (mac == null) mac = getLocalMac(); // 本地回退
return mac;
}
// 內部實現上述四個私有方法...
}
注意事項
- Windows 需管理員權限執行
nbtstat
- Linux
arp 輸出格式不同,分隔符為 :
- 防火牆可能阻擋 ICMP(ping)導致 ARP 刷新失敗
- 虛擬網卡、Docker 網卡會干擾本地 MAC 獲取,需按名稱過濾