java - Java NIO 选择器 OP_READ 未触发
问题描述
这现在为我工作
首先我创建这样的服务器:
Selector readSelector = Selector.open();
Selector acceptSelector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8088));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(acceptSelector, SelectionKey.OP_ACCEPT);
然后,在线程中运行它:
while (acceptSelector.isOpen()) {
acceptSelector.select();
Iterator<SelectionKey> iterator = acceptSelector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey next = iterator.next();
iterator.remove();
if (next.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(readSelector, SelectionKey.OP_READ);
System.out.println("SOCKET ACCEPT " + socketChannel.getRemoteAddress());
// There is working find, I can get console output
}
}
}
接下来,我尝试读取数据的下一部分:
readSelector.select();
System.out.println("READ SELECTOR"); // This never get triggered
Iterator<SelectionKey> iterator = acceptSelector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey next = iterator.next();
iterator.remove();
if (next.isReadable()) {
SocketChannel channel = (SocketChannel) next.channel();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(16);
channel.read(byteBuffer);
System.out.println("SOCKET READ " + byteBuffer);
}
}
为什么不触发readSelector.select()
?
客户端代码(为了方便测试,我没有在客户端使用 nio):
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8088));
Thread.sleep(1000L);
OutputStream outputStream = socketChannel.socket().getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("This is DATA");
dataOutputStream.flush();
InputStream inputStream = socketChannel.socket().getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
String readUTF = dataInputStream.readUTF();
System.out.println(readUTF);
顺便说一句:我见过一些这样的重用代码
Selector selector = Selector.open();
... ...
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
... ...
socketChannel.register(selector, SelectionKey.OP_READ);
ServerSocketChannel
并SocketChannel
使用相同的选择器,这将在我的演示中创建 NPE(接受返回 null),并且我使用if isAcceptable else if isReadable
确保我选择了正确的键。
Q1:为什么不触发 OP_READ?
Q2:为什么重用选择器会产生null?
解决方案
推荐阅读
- python - scikit-learn 回归预测结果太好了。我搞砸了什么?
- javascript - 数组中两个相邻数字之间的差异
- java - 方法完成后如何等待?
- java - 与通用方法的接口
- python - 为什么 argparse 顺序与可选参数有关?
- javafx - 将 VBox 添加到 MenuButton JavaFX
- vba - 如何返回登录后附加字符的 IE.LocationUrl?
- angular - 无法运行组件 Angular2
- android - 如何从 Android 单元测试中引用 MenuItem
- node.js - Nodejs App在本地运行良好,但在线启动时出现问题