2017-07-03 462 views
-1
fun main(args: Array<String>) { 
    val selector = Selector.open() 
    val sc = SocketChannel.open() 
    sc.configureBlocking(false) 
    sc.connect(InetSocketAddress(1234)) 
    val key = sc.register(selector, SelectionKey.OP_CONNECT) 
    println("key=$key") 
    key.attach(ClientAttachment()) 

    writeThread(sc) 

    while (selector.isOpen) { 
     if (selector.select() == 0) continue 

     val keys = selector.selectedKeys().iterator() 
     while (keys.hasNext()) { 
      val key = keys.next() 
      println("key=$key") 
      println("ac=${key.attachment()}") 
      keys.remove() 
      if (key.isConnectable) { 
       val c = key.channel() as SocketChannel 
       while (!c.finishConnect()) { 
        Thread.sleep(100) 
       } 
       println("連接服務器成功") 
       c.register(selector, SelectionKey.OP_READ) 
      } else if (key.isReadable) { 
       handleRead(key) 
      } 
     } 
    } 
} 

我創建一個SocketChannel,並將其註冊到選擇器,然後將一個對象附加到該鍵。有沒有關於java nio中的selectionKey.attachment()的任何錯誤?

當我收到第一個OP_CONNECT事件時,我可以成功獲取附件。 但在下一個OP_READ事件中,attachment()返回null?

爲什麼?

+0

您可能希望包含一個標記,指明您正在使用的語言。 – matt

+0

我打印的關鍵,它表明關鍵是一樣的。 – Tony

+0

哪條線似乎會導致問題? –

回答

1
c.register(selector, SelectionKey.OP_READ); 

這將創建一個新的註冊,以新SelectionKey:在這種情況下null,因爲你沒有提供的。如果您想要保留之前的附件,請使用新參數調用interestOps(),或者使用與之前相同的附件對象調用register(Selector, int, Object)

但是你的連接代碼是毫無意義的。你把頻道設置爲非阻塞模式,然後你基本上執行一個阻塞模式連接困難的方式,睡覺。如果您必須啓動選擇循環,請將通道置於阻止模式,執行連接,然後將其置於非阻塞模式。但是,除非你打算連接到很多服務器,或者一個有很多連接的服務器(如蜘蛛),否則在客戶端的非阻塞甚至是NIO的角色總是會逃脫我。

相關問題