1. Overview

Port scanning with Java is a method of enumerating the open or active ports of a target machine. The goal is mainly to list the open ports in order to know the applications and services that are currently running.

In this tutorial, we’ll explain how to develop a simple application for port scanning with Java that we can use to scan a host for open ports.

2. What Is a Computer Port?

A computer port is a logical entity that makes it possible to associate a particular service with a connection. Furthermore, a port is identified by an integer from 1 to 65535. By convention, the first 1024 are reserved for standard services such as:

  • Port 20: FTP
  • Port 23: Telnet
  • Port 25: SMTP
  • Port 80: HTTP

The idea of a port scanner is to create a TCP Socket and try to connect to a specific port. If the connection is successfully established, then we’ll mark this port as open, and if not, we’ll mark it as closed.

However, establishing a connection on each of the 65535 ports can take up to 200 ms per port. This may sound like a short amount of time, but in total, it would take a considerable amount of time to scan all ports of a single host one by one.

To solve the performance issue, we’ll use the multi-threaded approach. This can dramatically speed up the process compared to attempting to connect to each port sequentially.

3. Implementation

To implement our program, we create a function portScan() with two parameters as input:

  • ip: the IP address to scan; it’s equivalent to 127.0.0.1 for localhost
  • nbrPortMaxToScan: the maximal number of ports to scan; this number is equivalent to 65535 if we want to scan all ports

3.1. Implementation

Let’s see what our portScan() method looks like:

public void runPortScan(String ip, int nbrPortMaxToScan) throws IOException {
        ConcurrentLinkedQueue openPorts = new ConcurrentLinkedQueue<>();
        ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
        AtomicInteger port = new AtomicInteger(0);
        while (port.get() < nbrPortMaxToScan) {
                final int currentPort = port.getAndIncrement();
                executorService.submit(() -> {
                        try {
                                Socket socket = new Socket();
                                socket.connect(new InetSocketAddress(ip, currentPort), timeOut);
                                socket.close();
                                openPorts.add(currentPort);
                                System.out.println(ip + " ,port open: " + currentPort);
                        } catch (IOException e) {
                                System.err.println(e);
                        }
                });
        }
        executorService.shutdown();
        try {
                executorService.awaitTermination(10, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
                throw new RuntimeException(e);
        }
        List openPortList = new ArrayList<>();
        System.out.println("openPortsQueue: " + openPorts.size());
        while (!openPorts.isEmpty()) {
                openPortList.add(openPorts.poll());
        }
        openPortList.forEach(p -> System.out.println("port " + p + " is open"));
}

Our method returns a List with all open ports. To do so, we create a new Socket object to be used as a connector between two hosts. If a connection is successfully established, then we assume that the port is open, in which case we continue to the next line. On the other hand, if the connection fails, then we assume that the port is closed and a SocketTimeoutException is thrown and we are thrown to the exception catch block.

3.2. Multithreading

In order to optimize the amount of time needed to scan all 65535 Ports of the target machine, we’ll run our method concurrently. We use the ExecutorService, which encapsulates a pool of threads and a queue of tasks to be executed. All threads in the pool are still running.

The service checks if a task is to be processed in the queue and, if so, it withdraws the task and executes it. Once the task is executed, the thread waits again for the service to assign it a new task from the queue.

Furthermore, we use a FixedThreadPool with 10 Threads, which means that the program is going to run up to a maximum of 10 threads in parallel. We can adjust this pool size according to our machine configuration and capacities.

4. Conclusion

In this quick tutorial, we explained how to develop a simple application for port scanning with Java using Sockets and a multi-threaded approach.

As always, the code snippets are available over on GitHub.

Course – LS (cat=Java)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.