2017-07-03 464 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的角色总是会逃脱我。

相关问题