package com.it_jaros.networkScanner; import java.io.IOException; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.Socket; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; 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.AtomicLong; import java.util.concurrent.locks.LockSupport; public class Scanner { private Counter counter = new Counter(); public Scanner() {} public List scanPorts(ScanTarget target) { return scanPorts(target.address(), target.openSocketLimit(), target.delayInMillis()); } public List scanPorts(String address, int socketLimit, int delayInMillis) { Queue openPorts = new ConcurrentLinkedQueue<>(); Semaphore socketCap = new Semaphore(socketLimit); 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(); } }); } } System.out.println("Peak concurrent connects: " + counter.max()); return openPorts.stream().toList(); } }