commit fe3162771744e9a21970f089d0fe52cef86a758e
parent 9cf19128b665293c56e4b3b2f978190a44257776
Author: Matthias Jaros <jaros@mailbox.org>
Date: Mon, 26 Jan 2026 17:50:02 +0100
Added timeout to cli options
Diffstat:
4 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/src/main/java/com/it_jaros/networkScanner/App.java b/src/main/java/com/it_jaros/networkScanner/App.java
@@ -6,9 +6,9 @@ public class App {
public static void main(String[] args) {
CliParser cliParser = new CliParser();
try {
- ScanOptions target = cliParser.parseArgs(args);
- Scanner scanner = new Scanner(target.openSocketLimit());
- List<ScanResult> openPorts = scanner.scanPorts(target);
+ ScanOptions options = cliParser.parseArgs(args);
+ Scanner scanner = new Scanner(options.openSocketLimit(), options.timeoutInMillis());
+ List<ScanResult> openPorts = scanner.scanPorts(options);
printResults(openPorts);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
diff --git a/src/main/java/com/it_jaros/networkScanner/CliParser.java b/src/main/java/com/it_jaros/networkScanner/CliParser.java
@@ -13,6 +13,7 @@ public class CliParser {
Set<String> targets = new HashSet<>();
int socketLimit = 1000;
int delayInMillis = 0;
+ int timeoutInMillis = 1000;
for (int i = 0; i < args.length; i++) {
final String currentArg = args[i];
if (!currentArg.startsWith("-")) {
@@ -30,6 +31,9 @@ public class CliParser {
case "--delay", "-d":
delayInMillis = Integer.parseInt(args[++i]);
break;
+ case "--timeout", "-t":
+ timeoutInMillis = Integer.parseInt(args[++i]);
+ break;
default:
throw new IllegalArgumentException("No such param " + currentArg);
}
@@ -40,9 +44,9 @@ public class CliParser {
}
System.out.printf(
- "Scanning targets '%s' with socketLimit(%s), delayInMillis(%s) \n", targets, socketLimit, delayInMillis);
+ "Scanning targets '%s' with socketLimit(%s), delayInMillis(%s), timeoutInMillis(%s)\n", targets, socketLimit, delayInMillis, timeoutInMillis);
- return new ScanOptions(targets.stream().toList(), socketLimit, delayInMillis);
+ return new ScanOptions(targets.stream().toList(), socketLimit, delayInMillis, timeoutInMillis);
}
public void usageAndExit() {
@@ -53,6 +57,7 @@ public class CliParser {
Options:
--delay, -d: Waiting period in millis for connection attempts for a host
--socketLimit, -sl: Socket Connection limit for a host
+ --timeout, -t: Timeout per connection attempt
Examples:
java -jar scanner.jar localhost
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanOptions.java b/src/main/java/com/it_jaros/networkScanner/ScanOptions.java
@@ -2,4 +2,4 @@ package com.it_jaros.networkScanner;
import java.util.List;
-public record ScanOptions(List<String> targets, int openSocketLimit, int delayInMillis) {}
+public record ScanOptions(List<String> targets, int openSocketLimit, int delayInMillis, int timeoutInMillis) {}
diff --git a/src/main/java/com/it_jaros/networkScanner/Scanner.java b/src/main/java/com/it_jaros/networkScanner/Scanner.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
+import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
@@ -17,14 +18,18 @@ import java.util.concurrent.locks.LockSupport;
public class Scanner {
- private Counter counter = new Counter();
- private Semaphore socketCap;
+ private final Counter counter = new Counter();
+ private final Semaphore socketCap;
+ private final int timeoutInMillis;
- public Scanner(int socketLimit) {
+ public Scanner(int socketLimit, int timeoutInMillis) {
+ this.timeoutInMillis = timeoutInMillis;
socketCap = new Semaphore(socketLimit);
}
- public Scanner() {}
+ public Scanner() {
+ this(1000, 1000);
+ }
public List<ScanResult> scanPorts(ScanOptions target) {
return scanPorts(target.targets(), target.delayInMillis());
@@ -48,26 +53,31 @@ public class Scanner {
for (int port = 1; port < 65536; port++) {
final int currentPort = port;
executor.submit(() -> {
- if (delayInNanos > 0) {
- long mySlot = nextStartNanos.getAndAdd(delayInNanos);
- long wait = mySlot - System.nanoTime();
- if (wait > 0)
- LockSupport.parkNanos(wait);
- }
- socketCap.acquireUninterruptibly();
- counter.inc();
- try (Socket socket = new Socket()) {
- socket.connect(new InetSocketAddress(target, currentPort), 10000);
- openPorts.add(currentPort);
- } catch (ConnectException ignored) {
- } catch (IOException e) {
- System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
- } finally {
- counter.dec();
- socketCap.release();
- }
+ scanPortsAsync(target, delayInNanos, nextStartNanos, openPorts, currentPort);
});
}
return new ScanResult(target, openPorts);
}
+
+ private void scanPortsAsync(String target, long delayInNanos, AtomicLong nextStartNanos, Queue<Integer> openPorts,
+ int currentPort) {
+ if (delayInNanos > 0) {
+ long mySlot = nextStartNanos.getAndAdd(delayInNanos);
+ long wait = mySlot - System.nanoTime();
+ if (wait > 0)
+ LockSupport.parkNanos(wait);
+ }
+ socketCap.acquireUninterruptibly();
+ counter.inc();
+ try (Socket socket = new Socket()) {
+ socket.connect(new InetSocketAddress(target, currentPort), timeoutInMillis);
+ openPorts.add(currentPort);
+ } catch (ConnectException | SocketTimeoutException ignored) {
+ } catch (IOException e) {
+ System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
+ } finally {
+ counter.dec();
+ socketCap.release();
+ }
+ }
}