加速查找连接到Wifi网络的设备并获取设备名称

时间:2015-06-19 18:18:53

标签: java networking network-programming

我正在编写一个Java程序,它将显示连接到我的Wifi网络的设备的名称和IP地址。

我已经找到了IP地址部分。这是代码:

public static void main(String[] args) throws IOException {
    InetAddress localhost = InetAddress.getLocalHost();
    // this code assumes IPv4 is used   
    byte[] ip = localhost.getAddress();
    for (int i = 1; i <= 254; i++) {
        ip[3] = (byte) i;
        InetAddress address = InetAddress.getByAddress(ip);
        if (address.isReachable(1000)) {
            // machine is turned on and can be pinged
            System.out.println(address + "is online");
        } else if (!address.getHostAddress().equals(address.getHostName())) {
            // machine is known in a DNS lookup
            System.out.println(address + "is in a DNS lookup");
        } else {
            // the host address and host name are equal, meaning the host name could not be resolved
            System.out.println(address + " is not online");
        }
    }
}

此代码有效,它显示已连接设备的IP地址。
但是我面临两个问题:

  1. 我无法获取已连接设备的名称。我只能获得IP地址。
  2. 这个程序工作得很慢。完成需要254秒。
  3. 那么如何显示所连接设备的名称,有没有办法加速这个程序?

    感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

降低超时值是加快发现过程的一种方法,但Java 8带来了并行流。使用并行流,您可以并行发现远程网络设备而不是顺序,以及耗费时间的顺序流程。

以下是我尝试使用并行流来发现网络设备的方法。

public static void main(String[] args) throws Exception {
    byte[] localHostIp = InetAddress.getLocalHost().getAddress();
    List<DiscoverNetworkDevice> networkDevices = new ArrayList();
    for (int i = 1; i < 255; i++) {
        // Assuming IPV4
        localHostIp[3] = (byte) i;
        networkDevices.add(new DiscoverNetworkDevice(
                InetAddress.getByAddress(localHostIp).getHostAddress()));
    }

    discover(networkDevices);
    parallelDiscover(networkDevices);
}

public static void discover(List<DiscoverNetworkDevice> networkDevices) {
    long start = System.currentTimeMillis();

    Object[] discoveredDevices = networkDevices
            .stream()
            .filter(nd -> nd.Discover()).toArray();
    for (Object obj : discoveredDevices) {
        System.out.println(obj);
    }

    long end = System.currentTimeMillis();
    System.out.println("Elapsed: " + (end - start));
    System.out.println();
}

public static void parallelDiscover(List<DiscoverNetworkDevice> networkDevices) {
    long start = System.currentTimeMillis();

    Object[] discoveredDevices = networkDevices
            .parallelStream()
            .filter(nd -> nd.Discover()).toArray();
    for (Object obj : discoveredDevices) {
        System.out.println(obj);
    }

    long end = System.currentTimeMillis();
    System.out.println("Elapsed: " + (end - start));
    System.out.println();
}

public static class DiscoverNetworkDevice {
    private String hostIp;
    private String hostName;

    public DiscoverNetworkDevice(String hostIp) {
        this.hostIp = hostIp;
    }

    public boolean Discover() {
        try {
            InetAddress host = InetAddress.getByName(hostIp);
            if (host.isReachable(500)) {
                hostName = host.getHostName();
                return true;
            }
        } catch (IOException ioe) {
        }
        return false;
    }

    @Override
    public String toString() {
        return String.format("IP: %s \t Name: %s", hostIp, hostName);
    }
}

结果:

IP: 192.168.1.1      Name: 192.168.1.1
IP: 192.168.1.121    Name: 192.168.1.121
IP: 192.168.1.137    Name: 192.168.1.137
Elapsed: 126523

IP: 192.168.1.1      Name: 192.168.1.1
IP: 192.168.1.121    Name: 192.168.1.121
IP: 192.168.1.137    Name: 192.168.1.137
Elapsed: 16113

正如您所看到的,就处理时间而言,使用并行流会产生非常显着的差异。

至于名称再次为IP地址,请参阅InetAddress Documentation特别是

enter image description here

答案 1 :(得分:2)

  

这个程序工作得很慢。完成需要254秒。

我想我知道为什么。来自InetAddress documentation

public boolean isReachable(int timeout)
                throws IOException
  

超时值(以毫秒为单位)表示尝试应采取的最长时间。如果在获得答案之前操作超时,则认为主机无法访问。负值将导致抛出IllegalArgumentException。

这就是你的问题所在。如果您分配一秒作为timeout值,则如果所有主机都无法访问,则您的程序将需要254秒才能完成。尝试减少它。

答案 2 :(得分:0)

嗨,也许为时已晚,无法提出答案,我正在寻找同一问题的解决方案,也许我的回答对其他人有用 我认为扫描程序使用多线程来加速搜索 而且我的代码非常有效

public class NetLimiter {

public interface DiscoverDeviceEeventListener extends EventListener {
    public void discovered(Device device);
    public void failed(Device device);
}

DiscoverDeviceEeventListener discoverDeviceEventHandler = null;

public void setDiscoverDeviceEvent(DiscoverDeviceEeventListener handler) {
    this.discoverDeviceEventHandler = handler;
}

public class Device {

    private String hostIp;
    private String hostName;

    public Device(String hostIp) {

        this.hostIp = hostIp;
        EventListenerList l = new EventListenerList();

    }

    public boolean discover() {
        try {
            InetAddress host = InetAddress.getByName(hostIp);
            if (host.isReachable(1000)) {
                hostName = host.getHostName();
                if (discoverDeviceEventHandler != null) {
                    discoverDeviceEventHandler.discovered(this);
                }
                return true;
            } else if (discoverDeviceEventHandler != null) {
                discoverDeviceEventHandler.failed(this);
            }
        } catch (IOException ioe) {
            System.out.print(ioe);
        }
        return false;
    }

    @Override
    public String toString() {
        return String.format("IP: %s \t Name: %s", hostIp, hostName);
    }
}

String subnet = "";

public NetLimiter(String subnet) {
    this.subnet = subnet;
}

public void checkDevices() {

    for (int i = 1; i < 255; i++) {
        String host = subnet + "." + i;
        (new Thread(){
            @Override
            public void run(){
                     (new Device(host)).discover();
            }
        }).start();

    }

}



}

也许它对生成253线程有害,但是将它们分成多线程,就像在一个线程中每10个线程一样,它将有效地加速进程