繁体   English   中英

Java选择器NIO读取问题

[英]Java Selector NIO Reading problem

相关代码-注意指令只是一个具有几种对数据进行操作的方法的类。 创建一个新线程对读取的数据进行操作。

读线:

while(true) {
     System.out.println(".");
     if(selector.select(500) == 0)
          continue;

     System.out.println("processing read");

     for(SelectionKey sk : selector.keys()) {
          Instructions ins = myHashTable.get(sk);
          if(ins == null) { 
               myHashTable.put(sk, new Instructions(sk));
               ins = myHashTable.get(sk);
          }
          ins.readChannel();
     }
}

读通道

public void readChannel() {
     BufferedReader reader = new BufferedReader(Channels.newReader((ReadableByteChannel) this.myKey.channel(), "UTF-8"));
     Worker w = new Worker(this, reader.readLine());
     (new Thread(w)).start();
}

然后,新线程将调用更多Instructions方法。

当ins函数完成时,它可能会写入Writer:

Writer out = Channels.newWriter((WritableByteChannel) key.channel(), "UTF-8");
out.write(output);
out.flush();

我可以确认我的客户端(快闪影片),然后接收输出并对其执行操作。

最后, w退出。

从客户端收到第一条消息并成功处理之后, READ THREAD循环不再处理其他消息。 我相信该密钥已在选择器中注册并可以读取。 我通过循环检查所有键来检查通道上的isReadable和isRegistered是否可读,并且迄今为止在所有情况下结果均为true。 但是,当从客户端发送第二条消息时,我在读取线程中看到的唯一响应是“。”。 字符不是每半秒打印一次,而是连续更快地打印出来。 因此,我相信通道中存在数据,但是由于某些原因,选择器未选择任何键。

谁能帮我?

我认为您在这里缺少几点。

  • 首先,您应该在for循环中使用selector.selectedKeys()
    正如Vijay提到的。
  • 在处理完密钥后,应从selectedKeys中删除密钥。 否则,该键将不会自动删除,因此即使设置了感兴趣的操作位的一个键,选择器也可能会连续旋转。 (这可能是您的问题)。
  • 最后,如果通道已准备就绪,则应在通道上执行操作。 即,仅当isReadable()返回true时才读,而仅当isWritable()为true时才尝试写。 不要忘记验证密钥。

不应该

for(SelectionKey sk : selector.keys()) 

for(SelectionKey sk : selector.selectedKeys())

因为您只想处理当前选择操作中发生的那些事件?

由于您说select(500)在5秒钟前返回,因此我猜测您已向选择器注册了用于WRITE操作的通道。 大多数情况下,通道已准备好进行写操作。 因此,只有在数据可用于写入时才有必要将兴趣操作设置为“写入”。

请注意,您必须从所选键列表中删除该通道。 Select()不会为您做到这一点。 为此,最好使用迭代器:

Iterator<SelectionKey> key_interator = selector.selectedKeys().iterator();
while (key_interator.hasNext()) {
  ...
  key_interator.remove();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM