1

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

阅读主题:

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();

我可以确认我的客户(Flash 电影),然后接收并处理输出。

最后,w退出。

然而,在收到来自客户端的第一条消息并成功处理之后,READ THREAD循环不再处理更多消息。我相信密钥已在选择器中注册并准备好阅读。我已经通过循环所有键来检查它们是否可以在通道上使用 isReadable 和 isRegistered 读取,并且结果在迄今为止的所有情况下都是正确的。但是,当从客户端发送第二条消息时,我在读取线程中看到的唯一响应是“。” 字符不是每半秒打印一次,而是不断加快。那么,我相信数据在通道中,但由于某种原因,选择器没有选择任何键。

谁能帮我?

4

3 回答 3

3

我认为您在这里遗漏了几点。


  • 首先,您应该在Vijay 提到的 for 循环中使用 selector.selectedKeys() 。
  • 处理密钥后,应从 selectedKeys 中删除密钥。否则,该键将不会被自动删除,因此即使有一个键设置了感兴趣的操作位,选择器也可能会持续旋转。(这可能是您的问题)。
  • 最后,如果通道准备好,我们应该对通道执行操作。即,仅当 isReadable() 返回 true 时才读取,并且仅当 isWritable() 为 true 时才尝试写入。不要忘记验证密钥。
于 2011-09-06T19:14:08.460 回答
2

不应该

for(SelectionKey sk : selector.keys()) 

for(SelectionKey sk : selector.selectedKeys())

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

既然你说 select(500) 在 5 秒之前返回,我猜你已经为 WRITE 操作注册了一个选择器的频道。大多数情况下,通道已准备好写入。因此,只有当数据可用于写入时,才需要将兴趣操作设置为 WRITE。

于 2009-10-07T23:40:02.480 回答
0

请注意,您必须从选定键列表中删除通道。Select() 不会为您执行此操作。最好为此目的使用迭代器:

Iterator<SelectionKey> key_interator = selector.selectedKeys().iterator();
while (key_interator.hasNext()) {
  ...
  key_interator.remove();
}
于 2011-07-22T11:38:01.943 回答