0

I'm trying to detect devices connected to the network I'm currently on by pinging every one of them, and checking the "reachable" value. Here's the piece of code responsible for that, cycling through the IPs, pinging them and checking response:

        for (int i = 1; i <= 254; i++) {
            String addr = IPAddress;
            addr = addr.substring(0, addr.lastIndexOf('.') + 1) + i;
            InetAddress pingAddr = InetAddress.getByName(addr);

            //skips the IP of 'this' device
            if (pingAddr.getHostAddress().equals(IPAddress)) { continue; }

            try {

                //ping command
                Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 -w 1 " + addr);
                boolean reachable = (p1.waitFor() == 0);
                if (reachable) {
                    //add to list, if reachable
                    addrs.add(pingAddr);
                }

            } catch (IOException ex) {
            } catch (InterruptedException ex) {
            }
        }

For some reason, this piece of code detects only some devices. I have 3 laptops, 2 android devices and 1 PC to test on. Out of these, it successfuly detects 2 of the 3 laptops, both android devices and it fails to detect the PC. You can notice the "-w 1" in the command, I tried setting that to 100, only change was it was taking ages to finish, and still found the same devices.

I also already tried this method:

INetAddress.isReachable(int timeout);

But it turned even worse, since - at least what i found - it uses TCP echo, which not all the devices respond to (only my android devices did).

Also, the pinging is really slow. I already divided it into 4 threads, but still it could use a speed boost.

So, my final question would be: Why is the ping command not able to detect every device & is there any other method you could think of to achieve my goal?

2 Answers2

2

Maybe the PC is behind firewall ? Does it respond when You manually ping it ?

For better performance - try this:

for (int i = 1; i <= 254; i++) {
        String addr = ipLocal;
        addr = addr.substring(0, addr.lastIndexOf('.') + 1) + i;
        InetAddress pingAddr = InetAddress.getByName(addr);

        //skips the IP of 'this' device
        if (pingAddr.getHostAddress().equals(ipLocal)) { continue; }


        String[] command = {"CMD", "/c", "ping -n 1 -w 1 " + addr};
        ProcessBuilder probuilder = new ProcessBuilder(command);
        Process process = probuilder.start();

        InputStream is = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;

        while ((line = br.readLine()) != null) {
            CharSequence stats = "Packets: Sent = 1, Received = 1";
            if(line.contains(stats)){
                System.out.println(line);
                System.out.println(addr);
                //add to list, if reachable
                //addrs.add(pingAddr);
            }
        }
    }
BuMcha
  • 21
  • 2
  • Thanks for a useful answer. The firewall was really the "problem", although the other devices (same OS) are behind firewall too, and responded. Also thanks for the code update. However, is there any way of finding such devices, behind firewall? I need this code to be useful for example in some company network, being able to find devices on that network. If not, I will mark this question as accepted. – Tomáš Bulíček Jan 25 '17 at 13:11
  • With access to the router you could get information about connected machines. The second idea is to try nslookup command. – BuMcha Jan 25 '17 at 18:42
  • I just got to updating the code you sent me for better performance. However, I get this exception: I/System.out: java.io.IOException: Error running exec(). Command: [CMD, /c, ping -n 1 -w 1 192.168.1.245] Working Directory: null Environment: (too long to leave it here..) – Tomáš Bulíček Jan 25 '17 at 21:04
  • oops, I don't know why I assumed that you're using windows to this :) I can't test it now, but try to change the command to: `String[] command = {"ping -n 1 -w 1 " + addr};` – BuMcha Jan 26 '17 at 17:49
0

Some computers will not respond to a ping due to being behind a firewall (as @BuMcha mentioned) or due to their own settings. If you have control over the firewalls and individual machines, it's possible that you could get around this by tweaking settings everywhere, but that seems fragile.

An alternative might be to send Address Resolution Protocol (ARP) messages instead. Those would get broadcast, probably, but might allow you to get the information that you want in a more robust way. I'm not sure how to send those from Java, but this other question seems to address that specific point: Is there a way to send ARP request via Java?

Community
  • 1
  • 1
Brick
  • 3,998
  • 8
  • 27
  • 47