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,并将其注册到选择器,然后将一个Object附加到该键。
当我收到第一个OP_CONNECT事件时,我可以成功获得附件。 但在下一个OP_READ事件中,attachment()返回null?
为什么?
答案 0 :(得分:1)
c.register(selector, SelectionKey.OP_READ);
这会创建新注册,并使用新的SelectionKey
:在这种情况下为null
,因为您没有提供。如果您想保留以前的附件,只需使用新参数调用interestOps()
,或者使用与之前相同的附件对象调用register(Selector, int, Object)
。
但您的连接代码毫无意义。您将通道置于非阻塞模式,然后执行基本上阻塞模式连接困难的方式,与睡眠。只需将通道保留在阻塞模式下,执行连接,然后将其置于非阻塞模式(如果必须)并启动选择循环。但是,在客户端中,非阻塞,甚至是NIO的问题总是让我失望,除非你计划连接到许多服务器,或者一个连接有很多连接的服务器(比如蜘蛛)。 / p>