commit 523fe9cee4d4ddf4caa6a04dc5eabc13db5ea332
parent e0a012e946e71ba2e8769a70cc0055b5852d720d
Author: Matthias Jaros <jaros@mailbox.org>
Date: Mon, 26 Jan 2026 15:10:48 +0100
Added multi-target functionality
Diffstat:
6 files changed, 72 insertions(+), 44 deletions(-)
diff --git a/src/main/java/com/it_jaros/networkScanner/App.java b/src/main/java/com/it_jaros/networkScanner/App.java
@@ -6,10 +6,10 @@ public class App {
public static void main(String[] args) {
CliParser cliParser = new CliParser();
try {
- ScanTarget target = cliParser.parseArgs(args);
- Scanner scanner = new Scanner();
- List<Integer> openPorts = scanner.scanPorts(target);
- printResults(target, openPorts);
+ ScanOptions target = cliParser.parseArgs(args);
+ Scanner scanner = new Scanner(target.openSocketLimit());
+ List<ScanResult> openPorts = scanner.scanPorts(target);
+ printResults(openPorts);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
cliParser.usageAndExit();
@@ -18,9 +18,14 @@ public class App {
}
}
- public static void printResults(ScanTarget address, List<Integer> openPorts) {
- System.out.println("Target: " + address.address());
+ public static void printResults(List<ScanResult> results) {
+ results.forEach(r -> printResult(r));
+ }
+
+ private static void printResult(ScanResult result) {
+ System.out.println("Target: " + result.target());
System.out.print("Ports:");
- openPorts.forEach((p) -> System.out.print(" " + p));
+ result.openPorts().forEach((p) -> System.out.print(" " + p));
+ System.out.print("\n");
}
}
diff --git a/src/main/java/com/it_jaros/networkScanner/CliParser.java b/src/main/java/com/it_jaros/networkScanner/CliParser.java
@@ -1,19 +1,22 @@
package com.it_jaros.networkScanner;
+import java.util.HashSet;
+import java.util.Set;
+
public class CliParser {
- public ScanTarget parseArgs(String[] args) {
+ public ScanOptions parseArgs(String[] args) {
if (args.length < 1 || args[0].trim().equals("")) {
throw new IllegalArgumentException("No argument given");
}
- String target = null;
+ Set<String> targets = new HashSet<>();
int socketLimit = 1000;
int delayInMillis = 0;
for (int i = 0; i < args.length; i++) {
final String currentArg = args[i];
if (!currentArg.startsWith("-")) {
- target = currentArg;
+ targets.add(currentArg);
continue;
}
@@ -37,9 +40,9 @@ public class CliParser {
}
System.out.printf(
- "Scanning target '%s' with socketLimit(%s), delayInMillis(%s) \n", target, socketLimit, delayInMillis);
+ "Scanning targets '%s' with socketLimit(%s), delayInMillis(%s) \n", targets, socketLimit, delayInMillis);
- return new ScanTarget(target, socketLimit, delayInMillis);
+ return new ScanOptions(targets.stream().toList(), socketLimit, delayInMillis);
}
public void usageAndExit() {
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanOptions.java b/src/main/java/com/it_jaros/networkScanner/ScanOptions.java
@@ -0,0 +1,5 @@
+package com.it_jaros.networkScanner;
+
+import java.util.List;
+
+public record ScanOptions(List<String> targets, int openSocketLimit, int delayInMillis) {}
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanResult.java b/src/main/java/com/it_jaros/networkScanner/ScanResult.java
@@ -0,0 +1,5 @@
+package com.it_jaros.networkScanner;
+
+import java.util.Queue;
+
+public record ScanResult(String target, Queue<Integer> openPorts) {}
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanTarget.java b/src/main/java/com/it_jaros/networkScanner/ScanTarget.java
@@ -1,3 +0,0 @@
-package com.it_jaros.networkScanner;
-
-public record ScanTarget(String address, int openSocketLimit, int delayInMillis) {}
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.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -17,44 +18,56 @@ import java.util.concurrent.locks.LockSupport;
public class Scanner {
private Counter counter = new Counter();
+ private Semaphore socketCap;
+ public Scanner(int socketLimit) {
+ socketCap = new Semaphore(socketLimit);
+ }
+
public Scanner() {}
- public List<Integer> scanPorts(ScanTarget
- target) {
- return scanPorts(target.address(), target.openSocketLimit(), target.delayInMillis());
+ public List<ScanResult> scanPorts(ScanOptions target) {
+ return scanPorts(target.targets(), target.delayInMillis());
}
- public List<Integer> scanPorts(String address, int socketLimit, int delayInMillis) {
- Queue<Integer> openPorts = new ConcurrentLinkedQueue<>();
- Semaphore socketCap = new Semaphore(socketLimit);
+ public List<ScanResult> scanPorts(List<String> targets, int delayInMillis) {
+ List<ScanResult> results = new ArrayList<>();
long delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis));
- AtomicLong nextStartNanos = new AtomicLong(System.nanoTime());
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
- 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(address, currentPort));
- openPorts.add(currentPort);
- } catch (ConnectException ignored) {
- } catch (IOException e) {
- System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
- } finally {
- counter.dec();
- socketCap.release();
- }
- });
+ for (String target : targets) {
+ results.add(scanTargetAsync(target, delayInNanos, executor));
}
}
System.out.println("Peak concurrent connects: " + counter.max());
- return openPorts.stream().toList();
+ return results;
+ }
+
+ private ScanResult scanTargetAsync(String target, long delayInNanos, ExecutorService executor) {
+ AtomicLong nextStartNanos = new AtomicLong(System.nanoTime());
+ Queue<Integer> openPorts = new ConcurrentLinkedQueue<>();
+ 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));
+ openPorts.add(currentPort);
+ } catch (ConnectException ignored) {
+ } catch (IOException e) {
+ System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
+ } finally {
+ counter.dec();
+ socketCap.release();
+ }
+ });
+ }
+ return new ScanResult(target, openPorts);
}
}