2012-04-21 3 views
0

私はJavaのノンブロッキングIOを初めて使用しています。私は質問があります - サーバーからの新しいパケットがチャンネルから読み込みを完了した後に到着するが、セレクタからこのチャンネルの選択キーを削除する前に、セレクタによってノンブロッキングチャンネルの準備が失われますか?ここのコード例:NIO - チャンネルの準備状況を失うことはありますか?

 Selector selector; 

     // ...... 

     while (true) { 
      selector.select(); 
      Set<SelectionKey> set = selector.selectedKeys(); 

      Iterator<SelectionKey> iterator = set.iterator(); 
      while (iterator.hasNext()) { 
       SelectionKey key = iterator.next(); 
       SocketChannel channel = (SocketChannel) key.channel(); 
       ByteBuffer byteBuffer = ByteBuffer.allocate(GOOD_ENOUGH_CAPACITY); 
       while (channel.read(byteBuffer) > 0) ; 

       // HERE ! What happen if server started to write new message here? 
       // Will this channel be selected on next selector.select() ? 

       iterator.remove(); 

      } 
     } 
+2

からキーを削除する方法

key.cancel(); 

を使用する必要があります。チャンネルを読み書き可能(そしてinterestedOpsに応じて)している場合は、それを呼び出すときは重要ではありません。未読データがある場合、それは読み込み可能になります。選択したセットから削除しないと、明らかにそこにとどまります。サイドノート:NIO非/直接バッファを使用することはまれです。逆に、SSLEngineは内部implであるため直接バッファと一緒に使用されません。非直接バッファに関する部分を除き、byte [] – bestsss

+0

@bestsss +1に依存しています。データをコピーするだけの場合など、JVM自体にデータを取得する必要がない場合に便利です。アプリケーションプロトコルでリクエストやレスポンスを書いている場合は、ダイレクトバッファには反対表示されます。 – EJP

+0

@EJPでは、プロトコル用のダイレクトバッファーを引き続き使用できます。DataOutputStreamのようなものをバッファーにラップすることもできます。しかし、私の主な悩みはバイト(byte)のJava(Sunのimpl)です。 byte []はある時点で直接バッファにコピーされなければならない。 Javaはそれらを割り当て、ローカルのスレッドに「小さな」キャッシュを保持します。長いメッセージ(ソケットバッファより大きい)を書き込もうとするとかなり大きなダイレクトバッファが割り当てられます。次に、byte []全体が直接バッファにコピーされます。ソケットバッファはそれを保持することができないので、残りの部分は破棄され、プロセスは繰り返されます。オーバーヘッド... – bestsss

答えて

1

はい、あります。あなたはキーが選択時に「検証」されているセレクタ

+0

またはチャネルを閉じます。多くの人が両方をやっていますが、それは気まずいです。 – EJP

関連する問題