Android 通過讀取本地Arp表獲取當前區域網內其他裝置資訊
阿新 • • 發佈:2019-02-20
目的:獲取當前區域網內其他連線裝置的IP 和MAC資訊。
步驟:
1. 獲取本機wifi ip資訊;
2. 根據ip 去傳送ARP請求
3. 讀取本地ARP 表;
1. 獲取本機WiFi 下 ip :參考另一篇文章
2. ARP 簡介
- 地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取實體地址的一個TCP/IP協議。主機發送資訊時將包含目標IP地址的ARP請求廣播到網路上的所有主機,並接收返回訊息,以此確定目標的實體地址;收到返回訊息後將該IP地址和實體地址存入本機ARP快取中並保留一定時間,下次請求時直接查詢ARP快取以節約資源。
- ARP 快取
ARP快取是個用來儲存IP地址和MAC地址的緩衝區,其本質就是一個IP地址–>MAC地址的對應表,表中每一個條目分別記錄了網路上其他主機的IP地址和對應的MAC地址。每一個乙太網或令牌環網路介面卡都有自己單獨的表。當地址解析協議被詢問一個已知IP地址節點的MAC地址時,先在ARP快取中檢視,若存在,就直接返回與之對應的MAC地址,若不存在,才傳送ARP請求向區域網查詢。
為使廣播量最小,ARP維護IP地址到MAC地址對映的快取以便將來使用。ARP快取可以包含動態和靜態專案。動態專案隨時間推移自動新增和刪除。每個動態ARP快取項的潛在生命週期是10分鐘。新加到快取中的專案帶有時間戳,如果某個專案新增後2分鐘內沒有再使用,則此專案過期並從ARP快取中刪除;如果某個專案已在使用,則又收到2分鐘的生命週期;如果某個專案始終在使用,則會另外收到2分鐘的生命週期,一直到10分鐘的最長生命週期。靜態專案一直保留在快取中,直到重新啟動計算機為止.
- 在使用cmd arp -a 命令檢視 windows 下arp 表內容
3 在區域網內傳送廣播
普通的 arp 請求A要和B 建立連線,則 在區域網內傳送一個廣播 ,傳送源A的IP和MAC,目的ip 為B的IP,MAC 資訊為 FF:FF:FF:FF:FF:FF(表示廣播),但是現在我們不知道區域網內其他裝置的ip 資訊,因此,只能去逐個傳送請求。
// 根據ip 網段去 傳送arp 請求
private void discover(String ip) {
String newip = "";
if (!ip.equals("")) {
String ipseg = ip.substring(0, ip.lastIndexOf(".")+1);
for (int i=2; i<255; i++) {
newip = ipseg+String.valueOf(i);
if (newip.equals(ip)) continue;
Thread ut = new UDPThread(newip);
ut.start();
}
}
}
// UDPThread
public class UDPThread extends Thread {
private String target_ip = "";
public static final byte[] NBREQ = { (byte) 0x82, (byte) 0x28, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1,
(byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x20, (byte) 0x43, (byte) 0x4B,
(byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41,
(byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41,
(byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41,
(byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x0, (byte) 0x0, (byte) 0x21, (byte) 0x0, (byte) 0x1 };
public static final short NBUDPP = 137;
public UDPThread(String target_ip) {
this.target_ip = target_ip;
}
@Override
public synchronized void run() {
if (target_ip == null || target_ip.equals("")) return;
DatagramSocket socket = null;
InetAddress address = null;
DatagramPacket packet = null;
try {
address = InetAddress.getByName(target_ip);
packet = new DatagramPacket(NBREQ, NBREQ.length, address, NBUDPP);
socket = new DatagramSocket();
socket.setSoTimeout(200);
socket.send(packet);
socket.close();
} catch (SocketException se) {
} catch (UnknownHostException e) {
} catch (IOException e) {
} finally {
if (socket != null) {
socket.close();
}
}
}
}
4 . 讀取 ARP 表
private void readArp() {
try {
BufferedReader br = new BufferedReader(
new FileReader("/proc/net/arp"));
String line = "";
String ip = "";
String flag = "";
String mac = "";
while ((line = br.readLine()) != null) {
try {
line = line.trim();
if (line.length() < 63) continue;
if (line.toUpperCase(Locale.US).contains("IP")) continue;
ip = line.substring(0, 17).trim();
flag = line.substring(29, 32).trim();
mac = line.substring(41, 63).trim();
if (mac.contains("00:00:00:00:00:00")) continue;
Log.e("scanner", "readArp: mac= "+mac+" ; ip= "+ip+" ;flag= "+flag);
} catch (Exception e) {
}
}
br.close();
} catch(Exception e) {
}
}
- demo 已上傳github開啟連線
- 參考 普通ARP請求及迴應