10

I want to find all IP addresses of devices in the local network I'm currently connected to using Java code. The useful utility Advanced IP Scanner is able to find various IP addresses in my subnet of 192.168.178/24:

According to this answer, I built my code the following way:

import java.io.IOException;
import java.net.InetAddress;

public class IPScanner
{
    public static void checkHosts(String subnet) throws IOException
    {
        int timeout = 100;
        for (int i = 1; i < 255; i++)
        {
            String host = subnet + "." + i;
            if (InetAddress.getByName(host).isReachable(timeout))
            {
                System.out.println(host + " is reachable");
            }
        }
    }

    public static void main(String[] arguments) throws IOException
    {
        checkHosts("192.168.178");
    }
}

Unfortunately, this does not print out any results, meaning that no IP addresses are reachable. Why? There are devices in my local network like seen in the Advanced IP Scanner scan.

Community
  • 1
  • 1
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • I checked that code on my network, using broadcast, just mine IP or trying "www.google.com". Always says "not reachable". Check this answer: http://stackoverflow.com/questions/9922543/why-does-inetaddress-isreachable-return-false-when-i-can-ping-the-ip-address – Adam Michalik Sep 10 '15 at 11:33
  • 1
    Possible duplicate of [How to get a list of IP connected in same network (subnet) using Java](http://stackoverflow.com/questions/3345857/how-to-get-a-list-of-ip-connected-in-same-network-subnet-using-java) – jww Jan 28 '17 at 14:03

5 Answers5

7

Try to increase the timeout. I used about 5000ms, this helped me. In case you don't want to wait 5000ms * 254 = 21 minutes, try also this code with parallel pinging to the addresses:

public static void getNetworkIPs() {
    final byte[] ip;
    try {
        ip = InetAddress.getLocalHost().getAddress();
    } catch (Exception e) {
        return;     // exit method, otherwise "ip might not have been initialized"
    }

    for(int i=1;i<=254;i++) {
        final int j = i;  // i as non-final variable cannot be referenced from inner class
        new Thread(new Runnable() {   // new thread for parallel execution
            public void run() {
                try {
                    ip[3] = (byte)j;
                    InetAddress address = InetAddress.getByAddress(ip);
                    String output = address.toString().substring(1);
                    if (address.isReachable(5000)) {
                        System.out.println(output + " is on the network");
                    } else {
                        System.out.println("Not Reachable: "+output);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();     // dont forget to start the thread
    }
}

Worked perfectly for me.

The_Programmer
  • 186
  • 3
  • 12
  • Is there a reason you go from 1-254 and not 0-255? – dwb Jun 30 '20 at 14:03
  • 1
    In my network setup, the 0 is used as the default gateway and the 255 for broadcasting, therefore no device will be connected to neither of these addresses. – The_Programmer Jul 01 '20 at 20:51
3

InetAddress.isReachable will use ICMP ECHO REQUEST (as when you do a ping) or request on port 7 (echo port): http://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#isReachable%28int%29

Advance IP scanner perhaps use an other way to discover the hosts (like a request on radmin port or a request on http).

An host can be up but not answering to ICMP ECHO REQUEST.

have you try to ping one of the host from command line?

seneque
  • 279
  • 1
  • 5
1

Maybe try using InetAddress.getByAddress(host) instead of getByName, like this:

    InetAddress localhost = InetAddress.getLocalHost();
    byte[] ip = localhost.getAddress();

    for (int i = 1; i <= 254; i++)
    {
        try
        {
            ip[3] = (byte)i; 
            InetAddress address = InetAddress.getByAddress(ip);

            if (address.isReachable(100))
            {
                output = address.toString().substring(1);
                System.out.print(output + " is on the network");
            }
    }

I took this sample for autodetection code from here

vgm
  • 148
  • 1
  • 2
  • 12
  • Is it you, VGMoose? Cheers man ;) However, your code and application fails to find my Nintendo Wii console so your network scan is not working, sorry. File transfer works but I need to manually enter my Wii's IP address – BullyWiiPlaza Sep 17 '15 at 16:42
0

Java 8 stream solution

    IntStream.rangeClosed(1,254).mapToObj(num -> "192.168.0."+num).parallel()
            .filter((addr) -> {
                try {
                    return InetAddress.getByName(addr).isReachable(2000);
                } catch (IOException e) {
                    return false;
                }
            }
            ).forEach(System.out::println);
Ivo Skalický
  • 318
  • 1
  • 10
0
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class NetworkTest {
    private static final List<String> availableDevices = new ArrayList<>();
    private static String myNetworkIp;
    private static String deviceIpv4;

    public static void main(String[] args) {
        getDeviceIpv4();
        getMyNetworkIp();

        Thread thread = createScanningThreads(20);

        while (thread.isAlive()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        printAvailableDevices();
    }

    public static void scanDevices(int start, int end) {
        for (int i = start; i <= end; ++i) {
            try {
                InetAddress addr = InetAddress.getByName(myNetworkIp + i);

                if (addr.isReachable(1000)) {
                    System.out.println("Available: " + addr.getHostAddress()); 
                    availableDevices.add(addr.getHostAddress());
                } else
                    System.out.println("Not available: " + addr.getHostAddress());

            } catch (IOException ignored) {

            }
        }
    }

    public static void getMyNetworkIp() {
        for (int i = deviceIpv4.length() - 1; i >= 0; --i) {
            if (deviceIpv4.charAt(i) == '.') {
                myNetworkIp = deviceIpv4.substring(0, i + 1);
                break;
            }
        }
    }

    public static void getDeviceIpv4() {
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            deviceIpv4 = localhost.getHostAddress();

            if (deviceIpv4.equals("127.0.0.1")) {
                System.out.println("This PC is not connected to any network!");
            }
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

    public static Thread createScanningThreads(int threads) {
        Thread thread = null;

        for (int i = 0; i < threads; ++i) {
            int start = i * 256 / threads;
            int end = (i + 1) * 256 / threads - 1;
            System.out.println("Thread " + i + " will scan from " + start + " to " + end);

            thread = new Thread(() -> scanDevices(start, end));
            thread.start();
        }

        return thread;
    }

    public static void printAvailableDevices() {
        System.out.println("\nAll Connected devices(" + availableDevices.size() + "):");
        for (String availableDevice : availableDevices) System.out.println(availableDevice);
    }

}

Here's a code that uses Threads to scan all possible ipv4 addresses on your local network to get the list faster. The list of all ipv4 addresses will be stored in the List:

availableDevices
Rifle
  • 1