From 4b39ad9ba44f39e4c68d3592b1295f0044315f7d Mon Sep 17 00:00:00 2001 From: Matthias Jaros Date: Wed, 5 Aug 2026 17:42:08 +0200 Subject: Removed usage of selector and selectionkey and instead use locksupport and wait logic to utilize virtual threads park mechanism for performance improvement --- src/main/java/com/it_jaros/jscanner/Scanner.java | 44 +++++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/it_jaros/jscanner/Scanner.java b/src/main/java/com/it_jaros/jscanner/Scanner.java index 5277327..01185bb 100644 --- a/src/main/java/com/it_jaros/jscanner/Scanner.java +++ b/src/main/java/com/it_jaros/jscanner/Scanner.java @@ -3,8 +3,6 @@ package com.it_jaros.jscanner; import java.io.IOException; import java.io.InputStream; import java.net.*; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -12,6 +10,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.LockSupport; import java.util.function.Consumer; import java.util.function.Function; @@ -351,32 +350,35 @@ public class Scanner implements AutoCloseable { socketLimit.acquire(); scan.socketStart(); try( - SocketChannel socketChannel = SocketChannel.open(); - Selector isOpen = Selector.open() + SocketChannel socketChannel = SocketChannel.open() ) { socketChannel.configureBlocking(false); - SelectionKey isOpenKey = socketChannel.register(isOpen, SelectionKey.OP_CONNECT); socketChannel.connect(new InetSocketAddress(host, port)); - long deadlineNanos = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutInMillis); - long waitInMillis = Math.min(timeoutInMillis, 5); - while (isOpenKey.isValid() && !isOpenKey.isConnectable()) { - if (isOpen.select(waitInMillis) == 1) { - if (socketChannel.finishConnect()) { - result.setState(PortState.OPEN); - //if (bannerRecognition) { - // result.setBanner(getBanner(socket)); - //} - } else { - result.setState(PortState.FILTERED); - } + final long deadlineNanos = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutInMillis); + final long waitInNanos = TimeUnit.MILLISECONDS.toNanos(1000); + boolean isConnected = false; + while (!cancelled && !isConnected) { + long remainingNanos = deadlineNanos - System.nanoTime(); + if (remainingNanos <= 0) { break; } + LockSupport.parkNanos(Math.min(waitInNanos, remainingNanos)); + isConnected = socketChannel.finishConnect(); + } - if (deadlineNanos - System.nanoTime() < 0) { - result.setState(PortState.FILTERED); - break; - } + if (cancelled) { + return result; + } + + if (isConnected) { + result.setState(PortState.OPEN); + //if (bannerRecognition) { + // result.setBanner(getBanner(socket)); + //} + } else { + result.setState(PortState.FILTERED); } + } catch (SocketTimeoutException ignored) { result.setState(PortState.FILTERED); } catch (ConnectException ignored) { -- cgit v1.3.1