有没有关于java nio中的selectionKey.attachment()的错误?

时间:2017-07-03 08:40:47

标签: java kotlin nio

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?

为什么?

1 个答案:

答案 0 :(得分:1)

c.register(selector, SelectionKey.OP_READ);

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

但您的连接代码毫无意义。您将通道置于非阻塞模式,然后执行基本上阻塞模式连接困难的方式,与睡眠。只需将通道保留在阻塞模式下,执行连接,然后将其置于非阻塞模式(如果必须)并启动选择循环。但是,在客户端中,非阻塞,甚至是NIO的问题总是让我失望,除非你计划连接到许多服务器,或者一个连接有很多连接的服务器(比如蜘蛛)。 / p>