有没有关于在java nio selectionKey.attachment()的任何错误?

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,并将其注册到选择器,然后将一个对象附加到该键。

当我收到第一个OP_CONNECT事件时,我可以成功获取附件。 但在下一个OP_READ事件中,attachment()返回null?

为什么?

 c.register(selector, SelectionKey.OP_READ); 

这将创建一个新的注册,并带有一个新的SelectionKey :在这种情况下为null ,因为您没有提供一个。 如果你想保留之前的附件,只需要用新的参数调用interestOps() ,或者像以前那样用相同的附件对象调用register(Selector, int, Object)

但是你的连接代码是毫无意义的。 你把频道设置为非阻塞模式,然后你基本上执行一个阻塞模式连接困难的方式,睡觉。 只要保持通道处于阻塞模式,进行连接, 然后将其置于非阻塞模式(如果必须)并启动选择循环。 但是,除非你打算连接到很多服务器,或者一个有很多连接的服务器(如蜘蛛),否则在客户端的非阻塞甚至是NIO的角色总是会逃脱我。