4

在我的应用程序中,我需要扫描本地子网 (192.168.1.*) 以收集所有连接设备的 MAC 地址列表。

我目前使用以下策略:

  1. 同时启动 255 个 ping 命令Runtime.exec("ping -c 1 <addr>")
  2. 在每个返回的进程上使用waitFor()以收集退出代码
  3. 关闭进程的输入流并销毁它们
  4. 读取/proc/net/arp文件并解析 MAC 地址

在大多数情况下,这非常有效并提供了快速扫描。

但是在某些设备上(例如 android 1.5,有时在 >=4.0 上),执行会在进程创建时卡住(在成功启动几个之后),并且无法终止正在运行的线程。

您看到我可以尝试解决此问题的任何方法吗?或者任何其他不会花费太长时间的策略?

4

1 回答 1

8

这可以通过使用运行INetAddress.isReachable()方法的线程池来解决(而不是ping在本机进程中运行命令)。

private static final int NB_THREADS = 10;

public void doScan() {
    Log.i(LOG_TAG, "Start scanning");

    ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS);
    for(int dest=0; dest<255; dest++) {
        String host = "192.168.1." + dest;
        executor.execute(pingRunnable(host));
    }

    Log.i(LOG_TAG, "Waiting for executor to terminate...");
    executor.shutdown();
    try { executor.awaitTermination(60*1000, TimeUnit.MILLISECONDS); } catch (InterruptedException ignored) { }

    Log.i(LOG_TAG, "Scan finished");
}

private Runnable pingRunnable(final String host) {
    return new Runnable() {
        public void run() {
            Log.d(LOG_TAG, "Pinging " + host + "...");
            try {
                InetAddress inet = InetAddress.getByName(host);
                boolean reachable = inet.isReachable(1000);
                Log.d(LOG_TAG, "=> Result: " + (reachable ? "reachable" : "not reachable"));
            } catch (UnknownHostException e) {
                Log.e(LOG_TAG, "Not found", e);
            } catch (IOException e) {
                Log.e(LOG_TAG, "IO Error", e);
            }
        }
    };
}
于 2012-04-20T14:55:06.507 回答