NIO(Non Blocking IO)客户端服务端代码示例分析

同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理。

I/O多路复用底层一般用的Linux API(select,poll,epoll)来实现,他们的区别如下表:


应用场景:

NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,编程比较复杂, JDK1.4 开始支持

NIO 有三大核心组件: Channel(通道), Buffer(缓冲区),Selector(选择器)

1、channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组

2、channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理

3、selector 可以对应一个或多个线程

4、NIO 的 Buffer 和 channel 都是既可以读也可以写


server端代码示例:

NIO服务端程序详细分析:

1、创建一个 ServerSocketChannel 和 Selector ,并将 ServerSocketChannel 注册到 Selector 上

2、 selector 通过 select() 方法监听 channel 事件,当客户端连接时,selector 监听到连接事件, 获取到 ServerSocketChannel 注册时绑定的 selectionKey

3、selectionKey 通过 channel() 方法可以获取绑定的 ServerSocketChannel

4、ServerSocketChannel 通过 accept() 方法得到 SocketChannel

5、将 SocketChannel 注册到 Selector 上,关心 read 事件

6、注册后返回一个 SelectionKey, 会和该 SocketChannel 关联

7、selector 继续通过 select() 方法监听事件,当客户端发送数据给服务端,selector 监听到read事件,获取到 SocketChannel  注册时绑定的 selectionKey

8、selectionKey 通过 channel() 方法可以获取绑定的 socketChannel

9、将 socketChannel 里的数据读取出来

10、用 socketChannel 将服务端数据写回客户端

总结:NIO模型的selector 就像一个大总管,负责监听各种IO事件,然后转交给后端线程去处理

NIO相对于BIO非阻塞的体现就在,BIO的后端线程需要阻塞等待客户端写数据(比如read方法),如果客户端不写数据线程就要阻塞,NIO把等待客户端操作的事情交给了大总管 selector,selector 负责轮询所有已注册的客户端,发现有事件发生了才转交给后端线程处理,后端线程不需要做任何阻塞等待,直接处理客户端事件的数据即可,处理完马上结束,或返回线程池供其他客户端事件继续使用。还有就是 channel 的读写是非阻塞的。

Redis就是典型的NIO线程模型,selector收集所有连接的事件并且转交给后端线程,

线程连续执行所有事件命令并将结果写回客户端

客户端代码示例:

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容