2017-08-11 70 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秒。

當客戶端第一次連接時,沒關係。我們檢索密鑰,獲取頻道並接受傳入連接。

但問題是我有些不清楚的原因,我不斷檢索可接受的關鍵,並嘗試接受更多。 SocketChannel channel = serverChannel.accept();爲空,我得到NPE

但是我爲什麼總是通知接受的密鑰呢?我做錯了什麼?

回答

2

處理完畢後,您需要從所選集合中刪除每個SelectionKey。否則,您將再次獲得相同的事件,即使它沒有真正準備好:例如accept()將返回null。

你需要看一個教程。沒有好處,只是做出來。請參閱Oracle NIO教程。

+0

這是否也適用於讀取操作?我的意思是當我從某個頻道讀取某些內容時...我是否需要將它從所選集中刪除?或者只是取消它? –

+0

所有操作都是如此,因爲任何教程都會告訴你。幾乎不需要取消SelectionKey。 – EJP