jscanner

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit bce8b404b5f9d4f3016b9e6b67633ea99523fc44
parent fe3162771744e9a21970f089d0fe52cef86a758e
Author: Matthias Jaros <jaros@mailbox.org>
Date:   Mon, 26 Jan 2026 18:28:17 +0100

Added progress bar :-)

Diffstat:
Asrc/main/java/com/it_jaros/networkScanner/Progress.java | 6++++++
Asrc/main/java/com/it_jaros/networkScanner/ProgressBar.java | 47+++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main/java/com/it_jaros/networkScanner/Scanner.java | 20++++++++++++++++----
3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/it_jaros/networkScanner/Progress.java b/src/main/java/com/it_jaros/networkScanner/Progress.java @@ -0,0 +1,5 @@ +package com.it_jaros.networkScanner; + +import java.util.concurrent.atomic.AtomicInteger; + +record Progress(String host, int total, AtomicInteger done, AtomicInteger open) {} +\ No newline at end of file diff --git a/src/main/java/com/it_jaros/networkScanner/ProgressBar.java b/src/main/java/com/it_jaros/networkScanner/ProgressBar.java @@ -0,0 +1,47 @@ +package com.it_jaros.networkScanner; + +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class ProgressBar { + + private ScheduledExecutorService ui = Executors.newSingleThreadScheduledExecutor(); + + public void start(List<Progress> hosts) { + final int lines = hosts.size(); + System.out.print("\n\n"); + ui.scheduleAtFixedRate(() -> { + // move cursor UP to where bars start + System.out.print("\u001b[" + lines + "A"); + + for (Progress progress : hosts) { + System.out.print("\u001b[2K\r"); + System.out.println(bar( + progress.host() + " open=" + progress.open().get(), + progress.done().get(), + progress.total())); + } + }, 1, 200, TimeUnit.MILLISECONDS); + } + + public void stop() { + ui.shutdown(); + } + + public String bar(String label, int done, int total) { + int width = 30; + double pct = total == 0 ? 1.0 : (done / (double) total); + int filled = (int) (pct * width); + + String b = "[" + "#".repeat(filled) + "-".repeat(width - filled) + "]"; + int percent = (int) (pct * 100); + + return String.format("%-25s %s %3d%% (%d/%d)", label, b, percent, done, total); + } + + void onPortFinished(Progress p) { + p.done().incrementAndGet(); + } +} diff --git a/src/main/java/com/it_jaros/networkScanner/Scanner.java b/src/main/java/com/it_jaros/networkScanner/Scanner.java @@ -13,12 +13,14 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; public class Scanner { private final Counter counter = new Counter(); + private final ProgressBar progressBar = new ProgressBar(); private final Semaphore socketCap; private final int timeoutInMillis; @@ -38,22 +40,32 @@ public class Scanner { public List<ScanResult> scanPorts(List<String> targets, int delayInMillis) { List<ScanResult> results = new ArrayList<>(); long delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis)); - try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();) { + List<Progress> hosts = new ArrayList<>(); for (String target : targets) { - results.add(scanTargetAsync(target, delayInNanos, executor)); + Progress progress = new Progress(target, 65535, new AtomicInteger(), new AtomicInteger()); + hosts.add(progress); + results.add(scanTargetAsync(target, delayInNanos, executor, progress)); } + progressBar.start(hosts); } + + progressBar.stop(); System.out.println("Peak concurrent connects: " + counter.max()); return results; } - private ScanResult scanTargetAsync(String target, long delayInNanos, ExecutorService executor) { + private ScanResult scanTargetAsync(String target, 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; executor.submit(() -> { - scanPortsAsync(target, delayInNanos, nextStartNanos, openPorts, currentPort); + try { + scanPortsAsync(target, delayInNanos, nextStartNanos, openPorts, currentPort); + } finally { + progressBar.onPortFinished(p); + } }); } return new ScanResult(target, openPorts);