在写java nio的demo时,希望按照React的模式实现,对每一个已经就绪的请求,都在一个新的线程里处理。具体的代码如下面所示。
当一个客户端写完数据之后,断开连接时,会报错:
java.nio.channels.ClosedChannelException
显然这种写法是不合适或者不对的。看到网上用的是 attach() 方法
selectionKey.attach(new Acceptor(selector,selectionKey));
那么:
问题1: 我采用的写法,是哪里导致客户端关闭时报错,错误原因是什么?
问题2: attach()怎么用,为什么这种写法可以避免关闭客户端报错的情况?
使用单独线程,进行select操作。
new Thread(() -> {
try {
while (selector.select() > 0) {
for (SelectionKey selectionKey : selector.selectedKeys()) {
try {
selector.selectedKeys().remove(selectionKey);
if (selectionKey.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}
if (selectionKey.isReadable()) {
doRead(selectionKey);
}
} catch (IOException e) {
selectionKey.cancel();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
当遇到可读事件时,在一个新的线程里进行处理。
public void doRead(SelectionKey selectionKey) {
new Thread(() -> {
try {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
String content = "";
int c = 0;
while ((c = socketChannel.read(byteBuffer)) > 0) {
byteBuffer.flip();
content += charset.decode(byteBuffer);
}
System.out.println(content);
selectionKey.interestOps(SelectionKey.OP_READ);
if (c == -1) {
selectionKey.cancel();
socketChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
相关分类