NIO Server端多路复用开发的一般步骤是:
刚开始对NIO的写操作理解的不深,不知道为什么要注册写事件,何时注册写事件,为什么写完之后要取消注册写事件。
如果有channel在Selector上注册了SelectionKey.OP_WRITE事件,在调用selector.select();时,系统会检查内核写缓冲区是否可写(什么时候是不可写的呢,比如缓冲区已满,channel调用了shutdownOutPut等等),如果可写,selector.select();立即返回,随后进入key.isWritable()分支。
当然你在channel上可以直接调用write(…),也可以将数据发送出去,但这样不够灵活,而且可能浪费CPU。
看一个场景,服务端需要发送一个200M的Buffer,看看使用OP_WRITE事件和不使用的区别。
客户端开发的一般步骤:
起初对OP_CONNECT事件还有finishConnect不理解,OP_CONNECT事件何时触发,特别是为什么要在key.isConnectable()分支里调用finishConnect方法后才能进行读写操作。
首先,在non-blocking模式下调用socketChannel.connect(new InetSocketAddress(“127.0.0.1”,8080));连接远程主机,如果连接能立即建立就像本地连接一样,该方法会立即返回true,否则该方法会立即返回false,然后系统底层进行三次握手建立连接。连接有两种结果,一种是成功连接,第二种是异常,但是connect方法已经返回,无法通过该方法的返回值或者是异常来通知用户程序建立连接的情况,所以由OP_CONNECT事件和finishConnect方法来通知用户程序。不管系统底层三次连接是否成功,selector都会被唤醒继而触发OP_CONNECT事件,如果握手成功,并且该连接未被其他线程关闭,finishConnect会返回true,然后就可以顺利的进行channle读写。如果网络故障,或者远程主机故障,握手不成功,用户程序可以通过finishConnect方法获得底层的异常通知,进而处理异常。
注:write事件除了用上面的方法key.attach(buffer)带buffer内容给handler外,还可以直接在用channel.register方法的第三个参数attach携带要写的内容。当注册了写事件,并携带了要写的内容后,会在可写事件发生被select出来时,通过key.attachment()拿出携带的要写的内容,进行写处理。
转载自:https://blog.csdn.net/weixin_42168940/article/details/102817533