In this tutorial, we will explain how to create a Simple IP Scanner with Java.
Warning - It is illegal to scan someone's network without his or her permission. Such an action is considered an attack. You are, however, allowed to scan your private network.
In the previous tutorial, I explained how to create a Port Scanner. Both are core modules on a Network Monitor application.
What is an IP Scanner?
An IP Scanner is a tool that scans the local network by trying to create connections on all IPs in the network.
What are IP Scanners used for?
Security - you might want to know which devices are currently connected to your network.
Application usage - your application might need to be connected to different machines over TCP or HTTP. For that, it needs to know which devices are connected to your network.
How it works
The program defines a range of available IPs to test. Then it tries to communicate with each one of them. If the connection is established - this IP is marked as exist. Then it repeat the process for all other IPs in the local network.
Every network has lots of IPs. Trying to establish a connection on each one of them can take up to 500 ms. Since it takes a very long time to scan all IPs in the network, we designed this IP Scanner to run in parallel - using the ExecutorService interface in Java.
The Code
Code Explanation
Let's examine the scan() method.
The method gets two input parameters: a firstIpInTheNetwork and a numOfIps. And returns a List with all connected devices.
The Core Logic
We create a new InetAddress instance. This object is used to create a connection with a given IP address. The InetAddress has a getbyName() method - It determines the Host’s IP address, given the host's name. The hostname can either be a machine name or a textual representation of its IP address. It returns an instance of an InetAddress with the IP address of that host.
Next, we continue by invoking the isReachable() method with a 500 ms timeout. It returns True if it is reachable and False if it is not.
At this point, we add an “If” statement. If the host is reachable, we add its IP to the “ipSet” List.
Concurrent Run
In order to have a reasonable runtime, we will run this logic concurrently.
We use the ExecutorService interface and the Executors Factory class, which provide simple and easy to use implementations.
We will use a FixedThreadPool with 20 Threads - meaning the program will run in parallelism of 20. You can tweak this parameter depends on the HW you are using.
ExecutorService executorService = Executors.newFixedThreadPool(20);
The logic is running over all IP range in the network, for each iteration it calls the
executorService.submit(() -> { });
Note that the curly braces get a Runnable object - here, it runs the IP Scanner’s core logic.
Since it runs in parallel, the open IP address cannot be added to a regular list - it needs to use a Thread Safe List in order to avoid race conditions.
We chose to use “ConcurrentSkipListSet” to hold all IP addresses and AtomicInteger to track the current IP address I'm testing.
Synchronization - in order to make the scan() method synchronized, the concurrent block needs to wait for the Runnable task to be returned.
We achieved that by adding the executorService.shutdown() method at the end.
The Return Statement
At the end of the scan() method, we return the instance of the “ConcurrentSkipListSet”.
The complete project can be found here