NIO 聊天室内部逻辑(二)
nio 是啥 ? 非阻塞io,可以用于网络编程。
* 什么叫非阻塞io?读取的是时候,线程是非阻塞的。
* 具体一点:非阻塞指IO事件本身不阻塞,但是获取IO事件的select()方法阻塞。有点类似Redis底层实现,多路复用。
*
* 底层:nio采用的是基于Reactor模式的工作方式,io调用是不会被阻塞的,
* 什么是阻塞io?读取的时候,线程是阻塞的。
核心组件 : selector选择器 channel通道 buffer缓存区
buffer缓存区 容器的对象 , 存放数据
实质是一个数组(数据类型 byteBuffer核心,char,int等) 属性capability,limit,position,mark等
buffer.allocate(capability);
//在堆上创建大小的对象
buffer.put();
//往Buffer中写入数据 填充
buffer.flip();
//读写模式切换
buffer.get();
//从Buffer中读取数据
buffer.clear();
//清空Buffer缓存 NIO基于缓存,每次使用前都要clear
channel通道 数据来源或数据写入的目的地 ,用于读取和写入
-
SocketChannel:把它理解为 TCP 连接通道,简单理解就是 TCP 客户端(ServerSocketChannel对应服务端, 监听机器端口)
channel.read(buffer); //读操作 channel.write(buffer); //写操作
**Selector选择器 ** 多路复用, 一个选择器可以同时对多个channel进行监听
selector.select();
//获取通道信息
Iterator iterator = selector.selectedKeys().iterator();//遍历事件集合,判断事件完成
selector.close();
//关闭selector资源
实现步骤
-
创建 选择器Selector
Selector Selector=Selector.open();
-
创建 服务器套接字通道ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
-
将Channel设置为非阻塞模式,并注册到selector上
channel = serverSocketChannel.socket(); channel.configureBlocking(false); SelectionKey key= channel.register(selector,SelectionKey.OP_READ);
channel.register(); 第二个参数有四种事件
SelectionKey.OP_READ; 通道中有数据可以进行读取
SelectionKey.OP_WRITE; 可以往通道中写入数据
SelectionKey.OP_CONNECT; 成功建立 TCP 连接
SelectionKey.OP_ACCEPT; 接受 TCP 连接
-
监听服务器端下发的消息
// 阻塞监听, 如果有事件触发, 返回触发的事件个数 // 被触发的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中 // 下面开始遍历上述 selectedKeys 集合 try { int eventTriggerCount = selector.select(); } catch (IOException e) { e.printStackTrace(); }
-
处理服务器端发送的数据
如果监听到服务器下发数据 , 开始遍历当前触发事件的通道 , 调用该通道读取数据到缓冲区 , 之后显示该数据 ;
-
根据业务需要决定是否再次注册监听事件,重复执行第四步操作