From 100fad7d18565127b2b28243fa07f63476b0bd3f Mon Sep 17 00:00:00 2001 From: KNEMC <2014539504@qq.com> Date: Tue, 29 Sep 2026 10:48:49 +0800 Subject: [PATCH] cmt --- .idea/vcs.xml | 1 + .../network/AsynchronousDatagramChannel.java | 277 ++++++++++++++++++ .../cloud/network/klalb/KLALBController.java | 4 +- 3 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 src/org/kne/cloud/network/AsynchronousDatagramChannel.java diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 35eb1dd..8f85844 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/src/org/kne/cloud/network/AsynchronousDatagramChannel.java b/src/org/kne/cloud/network/AsynchronousDatagramChannel.java new file mode 100644 index 0000000..c96deb9 --- /dev/null +++ b/src/org/kne/cloud/network/AsynchronousDatagramChannel.java @@ -0,0 +1,277 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.SocketAddress; +import java.net.SocketOption; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.DatagramChannel; +import java.nio.channels.MembershipKey; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * 自制的 UDP AIO 通道,内部使用线程池模拟异步收包。 + * 用户只需设置回调,无需自己管理线程。 + * + * 完整委托了 DatagramChannel 的所有公共方法。 + */ +public class AsynchronousDatagramChannel implements AutoCloseable { + + private final DatagramChannel delegate; + private final ExecutorService workerPool; + private final AtomicBoolean running = new AtomicBoolean(true); + private volatile ReceiveHandler handler; + private final int bufferSize; + private int threadCount; + + // ==================== 回调接口 ==================== + + @FunctionalInterface + public interface ReceiveHandler { + void onReceive(SocketAddress from, ByteBuffer data); + } + + // ==================== 构造方法 ==================== + + public AsynchronousDatagramChannel() throws IOException { + this(65535, Runtime.getRuntime().availableProcessors()); + } + + public AsynchronousDatagramChannel(int bufferSize, int threadCount) throws IOException { + this.bufferSize = bufferSize; + this.delegate = DatagramChannel.open(); + delegate.configureBlocking(true); + this.threadCount=threadCount; + this.workerPool = Executors.newFixedThreadPool(threadCount, r -> { + Thread t = new Thread(r, "AsyncDatagramReader"); + t.setDaemon(true); + return t; + }); + + } + + public void startWorkers() { + + for (int i = 0; i < threadCount; i++) { + workerPool.submit(this::readerLoop); + } + } + + // ==================== 核心方法 ==================== + + public void setReceiveHandler(ReceiveHandler handler) { + this.handler = handler; + } + + private void readerLoop() { + ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); + while (running.get()) { + try { + buffer.clear(); + SocketAddress from = delegate.receive(buffer); + if (from == null) { + continue; + } + buffer.flip(); + ReceiveHandler localHandler = handler; + if (localHandler != null) { + localHandler.onReceive(from, buffer); + } + } catch (IOException e) { + if (running.get()) { + e.printStackTrace(); + } + break; + } + } + } + + public int send(ByteBuffer data, SocketAddress target) throws IOException { + return delegate.send(data, target); + } + + // ==================== DatagramChannel 委托方法 ==================== + + // --- 连接相关 --- + + public DatagramChannel connect(SocketAddress remote) throws IOException { + return delegate.connect(remote); + } + + public DatagramChannel disconnect() throws IOException { + return delegate.disconnect(); + } + + public boolean isConnected() { + return delegate.isConnected(); + } + + // --- 绑定相关 --- + + public DatagramChannel bind(SocketAddress local) throws IOException { + return delegate.bind(local); + } + + public SocketAddress getLocalAddress() throws IOException { + return delegate.getLocalAddress(); + } + + public SocketAddress getRemoteAddress() throws IOException { + return delegate.getRemoteAddress(); + } + + // --- 读写相关 --- + + public int read(ByteBuffer dst) throws IOException { + return delegate.read(dst); + } + + public long read(ByteBuffer[] dsts) throws IOException { + return delegate.read(dsts); + } + + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + return delegate.read(dsts, offset, length); + } + + public int write(ByteBuffer src) throws IOException { + return delegate.write(src); + } + + public long write(ByteBuffer[] srcs) throws IOException { + return delegate.write(srcs); + } + + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + return delegate.write(srcs, offset, length); + } + + // --- 接收相关 --- + + public SocketAddress receive(ByteBuffer dst) throws IOException { + return delegate.receive(dst); + } + + // --- 多播 (Multicast) --- + + public MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException { + return delegate.join(group, interf); + } + + public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException { + return delegate.join(group, interf, source); + } + + // --- 选项相关 --- + + public DatagramChannel setOption(SocketOption name, T value) throws IOException { + return delegate.setOption(name, value); + } + + public T getOption(SocketOption name) throws IOException { + return delegate.getOption(name); + } + + public Set> supportedOptions() { + return delegate.supportedOptions(); + } + + // --- 阻塞模式 --- + + + public boolean isBlocking() { + return delegate.isBlocking(); + } + + // --- 选择器相关 --- + + public SelectableChannel configureBlocking(boolean block) throws IOException { + return delegate.configureBlocking(block); + } + + public SelectorProvider provider() { + return delegate.provider(); + } + + public int validOps() { + return delegate.validOps(); + } + + public SelectionKey keyFor(Selector sel) { + return delegate.keyFor(sel); + } + + public SelectionKey register(Selector sel, int ops) throws ClosedChannelException { + return delegate.register(sel, ops); + } + + public SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException { + return delegate.register(sel, ops, att); + } + + // --- 状态查询 --- + + public boolean isOpen() { + return delegate.isOpen() && running.get(); + } + + public DatagramSocket socket() { + return delegate.socket(); + } + + // ==================== 关闭方法 ==================== + + @Override + public void close() throws Exception { + running.set(false); + workerPool.shutdownNow(); + delegate.close(); + } + + // ==================== 静态工厂方法 ==================== + + public static AsynchronousDatagramChannel open() throws IOException { + return new AsynchronousDatagramChannel(); + } + + public static AsynchronousDatagramChannel open(int bufferSize) throws IOException { + return new AsynchronousDatagramChannel(bufferSize, Runtime.getRuntime().availableProcessors()); + } + + public static AsynchronousDatagramChannel open(int bufferSize, int threadCount) throws IOException { + return new AsynchronousDatagramChannel(bufferSize, threadCount); + } + + // ==================== 测试示例 ==================== + + public static void main(String[] args) throws Exception { + int port = 4567; + AsynchronousDatagramChannel channel = AsynchronousDatagramChannel.open(); + channel.bind(new InetSocketAddress(port)); + + channel.setReceiveHandler((from, data) -> { + byte[] bytes = new byte[data.remaining()]; + data.get(bytes); + String msg = new String(bytes); + System.out.println("Received from " + from + ": " + msg); + }); + + System.out.println("Echo server running on port " + port); + System.out.println("Press Enter to stop..."); + System.in.read(); + + channel.close(); + System.out.println("Server stopped."); + } +} \ No newline at end of file diff --git a/src/org/kne/cloud/network/klalb/KLALBController.java b/src/org/kne/cloud/network/klalb/KLALBController.java index 745238e..7e5d2e1 100644 --- a/src/org/kne/cloud/network/klalb/KLALBController.java +++ b/src/org/kne/cloud/network/klalb/KLALBController.java @@ -686,7 +686,7 @@ public class KLALBController { context.syncToSystem(); // System.out.println(context); try { - NTPv4Protocol nvc = new NTPv4Protocol(context, + /*NTPv4Protocol nvc = new NTPv4Protocol(context, new MultiProtocolSocketAddress(iproxyname + "datagram","0.0.0.0",123)); srv6Router.addSRv6RouterListener(new SRv6RouterListener() { @@ -718,7 +718,7 @@ public class KLALBController { return true; }); } - }); + });*/ nvc2 = new NTPv4Protocol(context, new MultiProtocolSocketAddress("udp","0.0.0.0",0)); System.out.println(" Loaded: NTP Module");