I made a very simple port scanner, but it runs too slow, so I’m looking for a way to make it scan faster. Here is my code:
public boolean portIsOpen(String ip, int port, int timeout) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
return true;
} catch (Exception ex) {
return false;
}
}
This code tests if a specific port is open on a specific IP address. For timeout I used a minimum value of 200 because when I go lower it doesn’t have enough time to test the port.
It works well, but it takes too much time to scan from 0 to 65535. Is there another way that could maybe scan from 0 to 65535 in less than 5 minutes?
If you need 200 ms for each of the 65536 ports (in the worst case, a firewall is blocking everything, thus making you hit your timeout for every single port), the maths is pretty simple: you need 13k seconds, or about 3 hours and a half.
You have two (non-exclusive) options to make it faster:
Since the operation is I/O bound (in contrast to CPU-bound—that is, you spend time waiting for I/O, and not for some huge calculation to complete), you can use many, many threads. Try starting with 20. They would divide the 3 hours and a half among them, so the maximum expected time is about 10 minutes. Just remember that this will put pressure on the other side, i.e., the scanned host will see huge network activity with "unreasonable" or "strange" patterns, making the scan extremely easy to detect.
The easiest way (ie, with minimal changes) is to use the ExecutorService and Future APIs:
Then, you can do something like:
If you need to know which ports are open (and not just how many, as in the above example), you’d need to change the return type of the function to
Future<SomethingElse>, whereSomethingElsewould hold the port and the result of the scan, something like:Then, change
BooleantoScanResultin the first snippet, and returnnew ScanResult(port, true)ornew ScanResult(port, false)instead of justtrueorfalseActually, I noticed: in this particular case, you don’t need the ScanResult class to hold result + port, and still know which port is open. Since you add the futures to a List, which is ordered, and, later on, you process them in the same order you added them, you could have a counter that you’d increment on each iteration to know which port you are dealing with. But, hey, this is just to be complete and precise. Don’t ever try doing that, it is horrible, I’m mostly ashamed that I thought about this… Using the ScanResult object is much cleaner, the code is way easier to read and maintain, and allows you to, later, for example, use a
CompletionServiceto improve the scanner.