Search code examples
javaport-scanning

Java port scanner: How to print all consecutive closed ports as a range on one line?


Noob here trying to learn how to make a port scanner in Java. I want the code to take all consecutive closed ports and print on one line that they are closed, like "ports 1000 to 4000 are closed". Here is my code so far:

import java.net.*;
public class KalebPortScanner {

    public static void main(String[] args) {
        String host = "localhost"; // replace localhost with IP of device to scan from

        int startingPort = 0; 
        int endingPort = 65535;
        
        for (int port=startingPort;port<=endingPort;port++) {   
        
            try {
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(host, port),100);
            System.out.println(+port+ " open");
            socket.close();
        int goodPort = port;
        } catch (Exception e) {
            // TODO: if port is closed
            int badPort = port;
            //System.out.println(+badPort+ " to " +port+ " are closed");
            //System.out.println(+port+ " closed");
        }
        }

    }

}

It's basically a mess but I'm trying to understand how I can mark "badPort" as the lower of the closed ports and "goodPort" as the highest one, and then print it. I appreciate all advice for cleaning this up or ways to improve it. Thank you!

Tried making a variable "goodPort" which equals "port" as long as the port is open, and "badPort" which sets itself to "port" if it's closed, and then tries to put them in one System.out.println to give the user the range of closed ports.


Solution

  • I think you can create a class to hold the port range and state:

    public class PortRange {
        public int min;
        public int max;
    
        public final boolean isPortBusy;
    
        public PortRange(int minPort, boolean isPortBusy) {
            this.min = minPort;
            this.max = minPort;
            this.isPortBusy = isPortBusy;
        }
    }
    

    Then do something like this in main method:

    List<PortRange> portRanges = new LinkedList<>();
    PortRange portRange = null;
    
    for (int port = 0; port < 65536; port++) {
        boolean isPortBusy = isPortBusy(port);
    
        if (portRange == null) {
            portRange = new PortRange(port, isPortBusy);
        } else if (portRange.isPortBusy == isPortBusy) {
            portRange.max = port;
        } else {
            portRanges.add(portRange);
            portRange = new PortRange(port, isPortBusy);
        }
    }
    
    portRanges.add(portRange);
    

    In this code, the static method isPortBusy(port) returns true or false depending on whether the port is busy or not.

    Then iterate through the collection and display the result:

    portRanges.forEach(range -> System.out.printf("Port range %d-%d : %s%n", range.min, range.max, (range.isPortBusy ? "Busy" : "Free")));
    

    Example of output:

    enter image description here