1. 程式人生 > >Android 通過讀取本地Arp表獲取當前區域網內其他裝置資訊

Android 通過讀取本地Arp表獲取當前區域網內其他裝置資訊

目的:獲取當前區域網內其他連線裝置的IP 和MAC資訊。
步驟:
1. 獲取本機wifi ip資訊;
2. 根據ip 去傳送ARP請求
3. 讀取本地ARP 表;

1. 獲取本機WiFi 下 ip :參考另一篇文章

2. ARP 簡介

  1. 地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取實體地址的一個TCP/IP協議。主機發送資訊時將包含目標IP地址的ARP請求廣播到網路上的所有主機,並接收返回訊息,以此確定目標的實體地址;收到返回訊息後將該IP地址和實體地址存入本機ARP快取中並保留一定時間,下次請求時直接查詢ARP快取以節約資源。
  2. 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請求及迴應