commit 5ad5da3145232581d6ac17bd8b736fc54a7ecb5d
parent e2e964ef1eadc3ebe34adfcb63c46c6ad1eb4c30
Author: Matthias Jaros <jaros@mailbox.org>
Date: Mon, 16 Feb 2026 17:07:46 +0100
Added PortRange class that generates ports to scan
Diffstat:
2 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/src/main/java/com/it_jaros/networkScanner/PortRange.java b/src/main/java/com/it_jaros/networkScanner/PortRange.java
@@ -0,0 +1,67 @@
+package com.it_jaros.networkScanner;
+
+import java.util.BitSet;
+import java.util.NoSuchElementException;
+
+public class PortRange {
+
+ private static final int MIN_PORT = 1;
+ private static final int MAX_PORT = 65535;
+ private final BitSet portsRange = new BitSet(MAX_PORT);
+ private final BitSet available = new BitSet(MAX_PORT);
+
+ private int cursor;
+ private int done = 0;
+ private int total = 0;
+
+ public PortRange(String ports) {
+ if (ports == null || "".equals(ports)) {
+ // keep defaults
+ portsRange.set(1, 1024 + 1);
+ return;
+ }
+
+ String[] splitComma = ports.split(",");
+ for (String commaValue: splitComma) {
+ if (commaValue.contains("-")) {
+ String[] splitRange = commaValue.split("-");
+ if (splitRange.length > 2) {
+ throw new IllegalArgumentException(String.format("Argument contains too many '-'' %s", commaValue));
+ }
+
+ int start = Integer.parseInt(splitRange[0]);
+ int end = Integer.parseInt(splitRange[1]);
+ portsRange.set(start, end + 1);
+ } else {
+ portsRange.set(Integer.parseInt(commaValue));
+ }
+ }
+
+ available.or(portsRange);
+ cursor = available.nextSetBit(MIN_PORT);
+ }
+
+ public synchronized int next() {
+ int p = available.nextSetBit(cursor);
+ if (p > 0) {
+ available.clear(p);
+ cursor = p + 1;
+ done++;
+ return p;
+ }
+
+ throw new NoSuchElementException("Reached end of port range");
+ }
+
+ public synchronized boolean hasNext() {
+ return available.nextSetBit(cursor) > 0;
+ }
+
+ public int getTotal() {
+ return portsRange.cardinality();
+ }
+
+ public int getDone() {
+ return done;
+ }
+}
diff --git a/src/main/java/com/it_jaros/networkScanner/Scanner.java b/src/main/java/com/it_jaros/networkScanner/Scanner.java
@@ -34,18 +34,18 @@ public class Scanner {
}
public List<ScanResult> scanPorts(ScanOptions target) {
- return scanPorts(target.targets(), target.delayInMillis());
+ return scanPorts(target.targets(), target.delayInMillis(), new PortRange(target.ports()));
}
- public List<ScanResult> scanPorts(List<String> targets, int delayInMillis) {
+ public List<ScanResult> scanPorts(List<String> targets, int delayInMillis, PortRange portsRange) {
List<ScanResult> results = new ArrayList<>();
long delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis));
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();) {
List<Progress> hosts = new ArrayList<>();
for (String target : targets) {
- Progress progress = new Progress(target, 65535, new AtomicInteger(), new AtomicInteger());
+ Progress progress = new Progress(target, portsRange.getTotal(), new AtomicInteger(), new AtomicInteger());
hosts.add(progress);
- results.add(scanTargetAsync(target, delayInNanos, executor, progress));
+ results.add(scanTargetAsync(target, portsRange, delayInNanos, executor, progress));
}
progressBar.start(hosts);
}
@@ -55,11 +55,11 @@ public class Scanner {
return results;
}
- private ScanResult scanTargetAsync(String target, long delayInNanos, ExecutorService executor, Progress p) {
+ private ScanResult scanTargetAsync(String target, PortRange portRange, long delayInNanos, ExecutorService executor, Progress p) {
AtomicLong nextStartNanos = new AtomicLong(System.nanoTime());
Queue<Integer> openPorts = new ConcurrentLinkedQueue<>();
- for (int port = 1; port < 65536; port++) {
- final int currentPort = port;
+ while (portRange.hasNext()) {
+ final int currentPort = portRange.next();
executor.submit(() -> {
try {
scanPortsAsync(target, delayInNanos, nextStartNanos, openPorts, currentPort);