- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在关注this tutorial关于 Java NIO。我找到了似乎正确的 java 文件 Here 。我已经调整了代码以在单个端口而不是多个端口上运行,并且只是将数据输出到屏幕而不是将其回显给客户端。
当我运行代码时,我的版本和上面超链接上的版本似乎都没有正确处理 channel 。我只是根据笔记本电脑风扇的声音得出了这个结论,在快速输入几条 System.out.println()
消息后,我设法将问题范围缩小了一些。起初我以为 selector.select()
方法由于某种原因没有阻塞, channel 似乎是空的,但 while(hasContent)
循环不断迭代。
经过一番搜索,我发现了 this post并意识到也许我没有正确处理 key 。从 channel 读取数据后,我调整了代码以取消 while(iterator.hasNext())
循环底部的 if 语句中的 SelectionKey。
这似乎已经成功了,现在我收到一条消息,通知在 channel 关闭之前没有更多字节可供读取,并且总体上事情似乎运行得更顺利。
这是我迄今为止所做的代码,我对于如何实现它的想法是否正确?我是否在正确的时间点取消了 key ?
public class ServerRunnable implements Runnable {
private int serverPort;
private int queueLength;
public ServerRunnable(int serverPort, int queueLength) {
this.serverPort = serverPort;
this.queueLength = queueLength;
}
private boolean running;
private ServerSocketChannel serverSocketChannel;
private ByteBuffer buffer = ByteBuffer.allocate(1024);
@Override
public void run() {
try {
Selector selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(serverPort));
System.out
.println("DeviceServerV0.2 - Going to Listen for connections on port: "
+ serverSocket.getLocalPort());
running = true;
SelectionKey serverAcceptKey = serverSocketChannel.register(
selector, SelectionKey.OP_ACCEPT);
int count = 0;
while (running) {
int keyCount = selector.select();
System.out.println("keyCount: " + keyCount);
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = (SelectionKey) keyIterator.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
ServerSocketChannel ssc = (ServerSocketChannel) key
.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
// Here we add the new connection to the selector
SelectionKey newKey = sc.register(selector,
SelectionKey.OP_READ);
keyIterator.remove();
} else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
SocketChannel sc = (SocketChannel) key.channel();
// Going with this from the tutorial for now.
// TODO: Implement proper boolean controls here
while (true) {
buffer.clear();
int read = sc.read(buffer);
if (read <= 0) {
// System.out.println("Bytes read: " + read);
System.out
.println("No more bytes, breaking loop.");
break;
} else {
buffer.flip();
String result = new String(buffer.array());
System.out
.println("Buffer Contents: " + result);
}
}
keyIterator.remove();
key.cancel();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我还知道调用 ByteBuffer.array()
不会影响 byteBuffer 中的当前位置,因此它仍然看起来好像缓冲区尚未被读取。我应该以某种方式处理这个问题,还是在循环开始时调用 ByteBuffer.clear() 就足够了?
我打算继续尝试构建一个使用线程池来处理请求的 NIO 服务器,但我想确保到目前为止我对 NIO 的理解是正确的。
最佳答案
当 channel 的 readyOps()
包含 SelectionKey.OP_READ
时,它意味着可以读取一些数据,而不是可以读取整个 channel 直至其末尾。但这就是您在 while(true)
循环中所做的事情;您正在阅读并因此轮询一个 channel ,直到到达其末尾。
正确的处理方法是读取一次并且不要尝试再次读取,除非下一个select
报告有更多数据需要读取。
关于Java NIO SelectionKey 迭代器和键处理,我做得对吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28172221/
我花了相当多的时间尝试优化文件哈希算法,以尽可能地提高性能。 查看我之前的 SO 主题: Get File Hash Performance/Optimization FileChannel Byte
我不太明白它们之间有什么不同,所以我对这两个包有一些疑问。 在 Google 上浏览了一下之后,似乎 Oracle 决定使用更新和增强的 NIO.2 包来更新 NIO 包,作为 JDK7 版本的一部分
在 Java 1.4 之前,通过在不同的输入流/输出流之间移动字节来处理文件是常见的做法。 自 Java 1.4 起,其中 NIO已添加,建议使用 Channels 执行相同操作。 与 NIO2在 J
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我需要重写一些应该在 Java 6 VM 上运行的 Java 7 文件 IO 代码。 该实现使用了方便的 Java 7 功能,例如自动关闭、Paths 和 Files。 更具体地说,我需要处理像 /t
当我查看java中Scanner的源代码时,我发现一些让我困惑的事情 import java.nio.file.Path; import java.nio.*; 它们之间有什么区别,为什么它们不直接导
我的 Java 代码中几乎所有文件 I/O 操作都使用 java.nio.*。然而,在今天调试一段代码时,我注意到调试器 (Intellij IDEA 14) 显示了以下关于 java.nio.fil
奇怪的是,我无法在 Google 中找到 NIO.2 异步 IO 性能与通过 java.nio.channels.Selector 使用 NIO 的多路复用 IO 的明确答案。 所以,我的问题是:NI
我是初级 Java 程序员。 今天,我练习了如何在 java 中复制文件并尝试按照本教程进行操作 http://www.journaldev.com/861/4-ways-to-copy-file-i
我有一个指向绝对路径的 java.nio.Path: /home/user/project/resources/configuration.xml 我有第二个 java.nio.Path 指向项目的根
我开始使用java.nio.*,现在我想知道:为什么java.nio.Paths.get(..)不使用java.nio.Path 对象作为输入? 现在我总是做这样的事情: final Path bas
我是新手,正在学习 Java。我尝试在 Netbeans 7 中运行以下应用程序。 import java.io.*; import java.nio.file.*; import java.nio.
我的 Java 程序(见下文)有时会在 java.nio.File.move() 方法执行中因 java.nio.file.AccessDeniedException 崩溃。 我不明白为什么会抛出这个
所以我在这里阅读我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式),特别是关于 Proactor/Reactor 异步 IO 模式的部分。我可以看到通过使用可选 channel
我有一个方法如下,它已经正常运行了很长时间: private String loadFromFile(){ RandomAccessFile inFile = null; FileCh
我在 IntellijIDEA Community Edition 2017.3 版本中收到以下错误。该项目使用java版本“1.8.0-ea”。请给我一些解决问题的想法 Error:Internal
一 点睛 在 scatter-and-gather 场景下,可以将数据写入多个 Buffer 中。在 NIO 中,也能够同时操作多个缓冲区。在很多 Channel 实现类中,都提供了多个重载的 rea
I/O简介 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
我是一名优秀的程序员,十分优秀!