2017-08-11 17 views
0

接続を受け付けるだけの単純なNIOサーバーを実行しようとしています。最も簡単なNIOサーバーの例

public static void main(String[] args) throws IOException{ 
    Selector selector = Selector.open(); 
    ServerSocketChannel serverChannel = ServerSocketChannel.open(); 
    serverChannel.configureBlocking(false); 
    serverChannel.socket().bind(new InetSocketAddress("localhost", 1456)); 
    serverChannel.register(selector, SelectionKey.OP_ACCEPT); 
    while (true) { 
     try { 
      selector.select(); 
      Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); 
      while (keys.hasNext()) { 
       SelectionKey key = keys.next(); 
       if (key.isAcceptable()) 
        accept(key, selector); 
      } 
     } catch (IOException e) { 
      System.err.println("I/O exception occurred"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

private static void accept(SelectionKey key, Selector selector) throws IOException{ 
    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); 
    SocketChannel channel = serverChannel.accept(); 
    channel.configureBlocking(false);   //<------- NPE Here 
    channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true); 
    channel.setOption(StandardSocketOptions.TCP_NODELAY, true); 
    channel.register(selector, SelectionKey.OP_READ); 
} 

そして最も単純なI/Oクライアント:私はこのプロセスの両方を実行すると

public static void main(String[] ars) throws IOException{ 
     Socket s = new Socket("localhost", 1456); 
     OutputStream ous = s.getOutputStream(); 
     InputStream is = s.getInputStream(); 
     while (true) { 
      ous.write(new byte[]{1, 2, 3, 3, 4, 5, 7, 1, 2, 4, 5, 6, 7, 8}); 
      is.read(); 
     } 
    } 

私はNullPointterExceeption Sの束を取得します。

クライアントが初めて接続したときは問題ありません。キーを取得し、チャンネルを取得し、着信接続を受け入れます。

しかし問題は、私が受け入れられるキーを引き続き検索し、より受け入れようとする理由がわからないことです。 SocketChannel channel = serverChannel.accept();はnullで、私はNPEになります。

しかし、私はいつも受け入れられているキーで通知していますか?私は何を間違えたのですか?

答えて

2

処理後に選択したセットからそれぞれSelectionKeyを削除する必要があります。それ以外の場合は、実際には準備ができていなくても、同じイベントが再度発生します。たとえば、accept()はnullを返します。

チュートリアルを見る必要があります。いいえ、ただそれを作ることはありません。 Oracle NIOチュートリアルを参照してください。

+0

読み取り操作でも同様ですか?私はチャンネルから何かを読むときに...選択したセットから削除する必要がありますか?それともキャンセルしますか? –

+0

チュートリアルでお伝えしますように、すべての操作に当てはまります。 'SelectionKey'をキャンセルする必要はほとんどありません。 – EJP

関連する問題