文章目录
NIO
NIO网络编程模型
NIO简介
NIO:Non-blocking I/O 或 New I/O
编程模型
- 模型:对事物共性的抽象
- 编程模型:对编程共性的抽象
BIO网络模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RktlvAr7-1619948977392)
缺点
大量并发的情况下,接入的客户端接收过多就会出现问题。
- 阻塞式I/O模型(主要缺点)
- 弹性伸缩性能力差
- 多线程耗资源
NIO网络模型
- 非阻塞IO
- 弹性伸缩能力强
- 单线程节约资源
核心Selector
接收所有客户端selector链接,并且监听它们关心的事件,当事件发生之后,就会调用相应的事件处理器,来处理这个事件
NIO网络实现步骤
NIO核心
- Channel:通道
- Buffer:缓冲区
- Selector:选择器(多路复用器)
Channel
简介
- 双线性
- 非阻塞性
- 操作唯一性(buffer)
实现
- 文件类:FileChannel
- UDP:DatagramChannel
- TCP:ServerSocketChannel / SocketChannel
//服务器通过服务端socket创建channel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//Server bind port
serverSocketChannel.bind(new InetSocketAddress(8000));
//Server 监听 Client link, creat socketchannel link
SocketChannel SocketChannel = SocketChannel.accept();
//Client link distance host and port.
SocketChannel SocketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8000));
Buffer
简介
- 作用:读写Channel中数据
- 本质:一个内存区域
属性
- Capacity:容量(超过需要清空,才能继续)
- Position:位置(表示当前位置,最大可谓Capaciyu - 1,当读取数据时,buffer会从写模式转发为读模式,position会重置为0,读取数据时,position会向后可读位置)
- Limit:上限(表示最多可以读写多少数据)
- Mark:标记
使用
//初始化长度为10的byte类型的buffer
ByteBuffer.allocate(10);
/*
*position:0
*limit:10
*capacity:10
*/
//向byteBuffer中写入三个字节
byteBuffer.put("abc".getBytes(Charset.forName("UTF-8")));
/*
*position:3
*limit:10
*capacity:10
*/
//将byteBuffer从写模式切换成读模式
byteBuffer.flip();
/*
*position:0
*limit:3
*capacity:10
*/
//从byteBuffer中读取一个字节
byteBuffer.get();
/*
*position:1
*limit:3
*capacity:10
*/
//调用mark方法记录下当前position位置
byteBuffer.mark();
/*
*mark:1
*position:1
*limit:3
*capacity:10
*/
//1. 调用get方法读取下一个字节
//2. 调用reset方法将position重置到mark位置
byteBuffer.get();
byteBuffer.reset();
/*
*mark:1
*position:1
*limit:3
*capacity:10
*/
// 调用clear方法,将所有属性重置
byteBuffer.clear();
/*
*position:0
*limit:10
*capacity:10
*/
Selecot
简介
- 作用:IO就绪选择
- 地位:NIO网络编程基础
使用
//创建Selector
Selector selector = Selector.open();
//将channel注册到selector上,监听读就绪事件
SelectionKey selectionKey = channel.register(selector, selectionKey);
//阻塞等待channel有就绪事件发生
int selectNum = selector.select();
//获取发生就绪事件的channel集合
set<SelectionKey> selectedKeys = selector.selectedKeys();
SelectionKey简介
- 四个就绪状态常量
- 有价值的属性
NIO编程实现步骤
- 创建Selector
- 创建ServerSocketChannel,并绑定监听端口
- 将Channel设置为非阻塞模式
- 将Channel注册到Selector上,监听连接事件
- 循环调用Selector的select方法,检测就绪情况
- 调用selectedKeys方法获取就绪channel集合
- 判断就绪事件钟类,调用业务处理方法
- 根据业务需要决定是否再次注册监听事件,重复执行第三步操作
NIO缺点
- 麻烦:NIO类库和API繁杂
- 心累:可靠性能力补齐,工作量和难度大
- 有坑:Selector空轮询,导致CPU100%