NIO总结

本文详细解析了NIO中的SelectionKey机制,包括如何通过ServerSocketChannel和SocketChannel进行读写事件的注册与处理。讨论了短连接和长连接场景下的NIO应用策略,以及客户端与服务器端关闭连接的最佳实践。
摘要由CSDN通过智能技术生成

NIO

1、SelectionKey key = channel.register(Selector, ops) :


其中channel可以是ServerSocketChannel或者是SocketChannel。返回的key代表了一个Channel和Selector的绑定,并附上一个操作。
多次register,只要Selector不变,channel不变,则返回的SelectionKey对象不变,变的只是ops。


2、SelectionKey中读和写事件的就绪条件为:
读事件:OP_READ:当有数据可读,当客户端shutDownOutputStream,即服务器端读到流的末尾(-1),再或者是客户端关闭了连接,则都会见读事件加入到 通道 的就绪事件中去。
写事件:OP_WRITE:当可以写数据,或者当客户端关闭了连接,都会将 写事件 加入到 通道 的就绪事件中去。

上面提到的客户端关闭连接,会触发对应通道上 的读和写事件为就绪,但是只要服务器端执行 通道读 或者 通道写 都会出现异常。
因此建议在客户端不要去关闭socket通道,而只由服务器端去关闭连接。
  
3、可以将读和写分开注册到不同的Selector中去。

如果是短连接,则可以注册在一个Selector中。
流程: serverChannel.register(16)-->doaccept-->clientChannel.register(1)-->doread-->clientChannel.register(4)-->dowrite-->clientChannel.close()或者key.cancel;

即先在服务端的接受通道ServerSocketChannel中注册接受事件(OP_ACCEPT=16),
然后客户端请求连接过来,通过ServerSocketChannel获取得到Socket,然后accept,获取到SocketChannel clientChannel,即获取到服务端到客户单的连接通道。
然后再clientChannel上注册读事件(OP_READ=1)
然后执行读逻辑。
读完后,将clientChannel上注册写事件,注意这里返回的key没有变更,只是感兴趣的操作变更了。
然后执行写逻辑。
写完后,必须要关闭通道,或者key.cancel。

短连接用NIO实现的优势在于可以通过有限几个线程,对上千上万个客户端请求提供服务。

如果是要用NIO来实现长连接(这是一种假的长连接,并不是一个线程对应一个请求去提供服务。):

可以通过顺序来控制,先读再写,即接收连接后,先注册读事件,执行读,读完后,注册写,写完后,再注册读,如此重复之。
这种方式必须确保读的时候,一定要读到数据,否则等待读到数据。并且客户端传输过来的数据必须每次格式都一样,即提供的服务是一中格式(如HTTP)的。

或者:可以通过将通道注册在不同的Selector中来实现,每个Selector一个线程。(这也是HBase的做法),具体实现可以参看后面hbase分析。



如果不将注册的key cancel掉,则它会一直被认为是就绪key(即被Seletor.select()选出来)的问题,
这个理论是有前提的:
1、关闭了写通道,服务器端读到了末尾(-1),此时读事件会一直就绪,即一直读到 -1,需要服务器端读到 -1 时做处理。
2、客户端关闭了 socket ,此时通道上 读 和 写 事件都会认为是 就绪的,这里也需要服务端处理。
3、只要在通道上的SelectionKey添加了对写事件感兴趣,在服务器端未关闭通道或者未将写事件去除掉之前,此通道都会被认为是可以写的。
 
现在将 读 写 事件的就绪条件总结如下,以此更正:
SelectionKey中读和写事件的就绪条件为:
 
读事件:OP_READ:当有数据可读,当客户端socket.shutdownOutput() ,即服务器端读到流的末尾(-1),再或者是客户端关闭了连接,则都会将 读事件 加入到 通道 的就绪事件中去。
写事件:OP_WRITE:当可以写数据,或者当客户端关闭了连接,都会将 写事件 加入到 通道 的就绪事件中去。
 
上面提到的客户端关闭连接,会触发对应通道上 的读和写事件为就绪,但是只要服务器端执行 通道读 或者 通道写 都会出现异常。
因此建议在客户端不要去关闭socket通道,而只由服务器端去关闭连接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值