diff --git a/hutool-socket/src/main/java/cn/hutool/socket/nio/ChannelHandler.java b/hutool-socket/src/main/java/cn/hutool/socket/nio/ChannelHandler.java
index 84a9d1e7f..248b8a734 100644
--- a/hutool-socket/src/main/java/cn/hutool/socket/nio/ChannelHandler.java
+++ b/hutool-socket/src/main/java/cn/hutool/socket/nio/ChannelHandler.java
@@ -6,12 +6,14 @@ import java.nio.channels.SocketChannel;
* NIO数据处理接口,通过实现此接口,可以从{@link SocketChannel}中读写数据
*
*/
+@FunctionalInterface
public interface ChannelHandler {
/**
* 处理NIO数据
*
* @param socketChannel {@link SocketChannel}
+ * @throws Exception 可能的处理异常
*/
- void handle(SocketChannel socketChannel);
+ void handle(SocketChannel socketChannel) throws Exception;
}
diff --git a/hutool-socket/src/main/java/cn/hutool/socket/nio/NioClient.java b/hutool-socket/src/main/java/cn/hutool/socket/nio/NioClient.java
index 07a3de382..738f9c584 100644
--- a/hutool-socket/src/main/java/cn/hutool/socket/nio/NioClient.java
+++ b/hutool-socket/src/main/java/cn/hutool/socket/nio/NioClient.java
@@ -3,6 +3,7 @@ package cn.hutool.socket.nio;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.socket.SocketRuntimeException;
import java.io.Closeable;
import java.io.IOException;
@@ -19,9 +20,11 @@ import java.util.Iterator;
* @author looly
* @since 4.4.5
*/
-public abstract class NioClient implements Closeable {
+public class NioClient implements Closeable {
+
private Selector selector;
private SocketChannel channel;
+ private ChannelHandler handler;
/**
* 构造
@@ -68,6 +71,17 @@ public abstract class NioClient implements Closeable {
return this;
}
+ /**
+ * 设置NIO数据处理器
+ *
+ * @param handler {@link ChannelHandler}
+ * @return this
+ */
+ public NioClient setChannelHandler(ChannelHandler handler){
+ this.handler = handler;
+ return this;
+ }
+
/**
* 开始监听
*/
@@ -106,18 +120,14 @@ public abstract class NioClient implements Closeable {
// 读事件就绪
if (key.isReadable()) {
final SocketChannel socketChannel = (SocketChannel) key.channel();
- read(socketChannel);
+ try{
+ handler.handle(socketChannel);
+ } catch (Exception e){
+ throw new SocketRuntimeException(e);
+ }
}
}
- /**
- * 处理读事件
- * 当收到读取准备就绪的信号后,回调此方法,用户可读取从客户端传出来的消息
- *
- * @param socketChannel SocketChannel
- */
- protected abstract void read(SocketChannel socketChannel);
-
/**
* 实现写逻辑
* 当收到写出准备就绪的信号后,回调此方法,用户可向客户端发送消息
diff --git a/hutool-socket/src/main/java/cn/hutool/socket/nio/NioServer.java b/hutool-socket/src/main/java/cn/hutool/socket/nio/NioServer.java
index 2ce10cc33..632bb2b44 100644
--- a/hutool-socket/src/main/java/cn/hutool/socket/nio/NioServer.java
+++ b/hutool-socket/src/main/java/cn/hutool/socket/nio/NioServer.java
@@ -3,6 +3,7 @@ package cn.hutool.socket.nio;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.log.Log;
+import cn.hutool.log.StaticLog;
import java.io.Closeable;
import java.io.IOException;
@@ -135,7 +136,12 @@ public class NioServer implements Closeable {
// 读事件就绪
if (key.isReadable()) {
final SocketChannel socketChannel = (SocketChannel) key.channel();
- handler.handle(socketChannel);
+ try{
+ handler.handle(socketChannel);
+ } catch (Exception e){
+ IoUtil.close(socketChannel);
+ StaticLog.error(e);
+ }
}
}
diff --git a/hutool-socket/src/test/java/cn/hutool/socket/nio/NioClientTest.java b/hutool-socket/src/test/java/cn/hutool/socket/nio/NioClientTest.java
index a39f04f40..e993e4bb3 100644
--- a/hutool-socket/src/test/java/cn/hutool/socket/nio/NioClientTest.java
+++ b/hutool-socket/src/test/java/cn/hutool/socket/nio/NioClientTest.java
@@ -1,58 +1,49 @@
package cn.hutool.socket.nio;
+import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.lang.Console;
-import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import java.nio.ByteBuffer;
-import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NioClientTest {
@SneakyThrows
public static void main(String[] args) {
- NioClient client = new NioClient("127.0.0.1", 8080) {
-
- @SneakyThrows
- @Override
- protected void read(SocketChannel sc) {
- ByteBuffer readBuffer = ByteBuffer.allocate(1024);
- //从channel读数据到缓冲区
- int readBytes = sc.read(readBuffer);
- if (readBytes > 0) {
- //Flips this buffer. The limit is set to the current position and then
- // the position is set to zero,就是表示要从起始位置开始读取数据
- readBuffer.flip();
- //returns the number of elements between the current position and the limit.
- // 要读取的字节长度
- byte[] bytes = new byte[readBuffer.remaining()];
- //将缓冲区的数据读到bytes数组
- readBuffer.get(bytes);
- String body = StrUtil.utf8Str(bytes);
- Console.log("the read client receive message: " + body);
- } else if (readBytes < 0) {
- sc.close();
- }
+ NioClient client = new NioClient("127.0.0.1", 8080);
+ client.setChannelHandler((sc)->{
+ ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+ //从channel读数据到缓冲区
+ int readBytes = sc.read(readBuffer);
+ if (readBytes > 0) {
+ //Flips this buffer. The limit is set to the current position and then
+ // the position is set to zero,就是表示要从起始位置开始读取数据
+ readBuffer.flip();
+ //returns the number of elements between the current position and the limit.
+ // 要读取的字节长度
+ byte[] bytes = new byte[readBuffer.remaining()];
+ //将缓冲区的数据读到bytes数组
+ readBuffer.get(bytes);
+ String body = StrUtil.utf8Str(bytes);
+ Console.log("[{}]: {}", sc.getRemoteAddress(), body);
+ } else if (readBytes < 0) {
+ sc.close();
}
- };
+ });
client.listen();
- ByteBuffer buffer = ByteBuffer.wrap("client 发生到 server".getBytes());
- client.write(buffer);
- buffer = ByteBuffer.wrap("client 再次发生到 server".getBytes());
- client.write(buffer);
+ client.write(BufferUtil.createUtf8("你好。\n"));
+ client.write(BufferUtil.createUtf8("你好2。"));
// 在控制台向服务器端发送数据
- Console.log("请在下方畅所欲言");
+ Console.log("请输入发送的消息:");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String request = scanner.nextLine();
if (request != null && request.trim().length() > 0) {
- client.write(
- CharsetUtil.CHARSET_UTF_8
- .encode("测试client" + ": " + request));
+ client.write(BufferUtil.createUtf8(request));
}
}
}
diff --git a/hutool-socket/src/test/java/cn/hutool/socket/nio/NioServerTest.java b/hutool-socket/src/test/java/cn/hutool/socket/nio/NioServerTest.java
index 53212ed37..f1d74b3ea 100644
--- a/hutool-socket/src/test/java/cn/hutool/socket/nio/NioServerTest.java
+++ b/hutool-socket/src/test/java/cn/hutool/socket/nio/NioServerTest.java
@@ -1,5 +1,6 @@
package cn.hutool.socket.nio;
+import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Console;
@@ -28,7 +29,8 @@ public class NioServerTest {
//将缓冲区的数据读到bytes数组
readBuffer.get(bytes);
String body = StrUtil.utf8Str(bytes);
- Console.log("the read server receive message: " + body);
+ Console.log("[{}]: {}", sc.getRemoteAddress(), body);
+
doWrite(sc, body);
} else if (readBytes < 0) {
IoUtil.close(sc);
@@ -41,16 +43,8 @@ public class NioServerTest {
}
public static void doWrite(SocketChannel channel, String response) throws IOException {
- response = "我们已收到消息:" + response;
- if (!StrUtil.isBlank(response)) {
- byte[] bytes = response.getBytes();
- //分配一个bytes的length长度的ByteBuffer
- ByteBuffer write = ByteBuffer.allocate(bytes.length);
- //将返回数据写入缓冲区
- write.put(bytes);
- write.flip();
- //将缓冲数据写入渠道,返回给客户端
- channel.write(write);
- }
+ response = "收到消息:" + response;
+ //将缓冲数据写入渠道,返回给客户端
+ channel.write(BufferUtil.createUtf8(response));
}
}
\ No newline at end of file