diff options
| author | 2026-01-26 18:28:17 +0100 | |
|---|---|---|
| committer | 2026-07-09 09:59:28 +0200 | |
| commit | 46bf5d3df637a485c52e8fcd8374c10b4fb585b3 (patch) | |
| tree | 7899d441c50d9364121cb1597dfe49db26321bb7 | |
| parent | f450739603686f10e0e1b0b7da9b9a39dfb999db (diff) | |
Added progress bar :-)
3 files changed, 68 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 new file mode 100644 index 0000000..37a562b --- /dev/null +++ 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 new file mode 100644 index 0000000..50397f3 --- /dev/null +++ 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 index eb3af29..fae1890 100644 --- 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); |
