NIO服务端与客户端简易实现
NIO简介
Non-blocking I/O 或 New I/O
jdk1.4发布 1.8稳定
高并发网络服务器支持岗
编程模型
模型:对事务共性的抽象
编程模型:对编程共性的抽象
BIO网络模型缺点
阻塞式I/O模型
弹性伸缩能力差
多线程耗资源
大量并发情况下会出现多个线程等待,致使服务器压力增大,甚至使服务器崩掉
NIO网络模型猜想
Selector用于管理连接的客户端
NIO网络模型改进
基于非阻塞I/O实现
弹性伸缩能力强
单线程节省资源
NIO网络编程详解:NIO核心
Channel:通道
Buffer:缓冲区
Selector:选择器或多路复用器
Channel简介
双向性
非阻塞性
操作唯一性
Channel实现
文件类:FileChannel
UDP类:DatagramCHannel
TCP类:ServerSocketChannel/SocketChannel
Buffer简介
作用:读写Channel中数据
本质:一块内存区域
Buffer属性
Capacity:容量–表明数组最大容量字节数,如果超过容量必须将其清空才能继续填充数据
Position:位置–表示当前位置,插入数据后会向后移动到可插入数据单元,初始值为0,最大为下标减1
Limit:上限
Mark:标记
Selector简介
作用:I/O就绪选择
地位:NIO网络编程的基础
一个线程管理多个连接
SelectionKey简介
四种就绪状态常量
有价值的属性
NIO编程实现步骤
第一步:创建Selector
第二步:创建ServerSocketChannel,并绑定监听端口
第三步:将Channel设置为非阻塞模式
第四步:将Channel注册到Selector上,监听连接实际那
第五步:循环掉用Selector的select方法,检测就绪情况
第六步:掉用selectedKeys方法获取就绪channel集合
第七步:判断就绪事件种类,掉用业务处理方法
第八步:根据业务需要决定是否再次这个测监听时间,重复执行第三步操作
NIO网络编程实战
利用NIO编程只是,实现多人聊天室
NIO网络编程缺陷
麻烦:NOI类库和API繁杂
心累:可靠性能力补全,工作了和难度都非常大
有坑:Selector空轮询,导致CPU100% 主要体现在Linux系统
Server端
package com.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
/**
* NIO服务器端
*
* @author Wangjinghao
* @version v1.0.0
* @date 2019/6/11
*/
public class NioServer {
/* *
* @Author Wangjinghao
* @Description //TODO 启动
* @Date 16:21 2019/6/11
* @Param []
* @return void
**/
public void start() throws IOException {
/**
* 1.创建Selector
*/
Selector selector = Selector.open();
/**
* 2.通过ServerSocketChannel创建Channel通道
*/
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
/**
* 3.为channel通道绑定监听端口
*/
serverSocketChannel.bind(new InetSocketAddress(8000));
/**
* 4. **设置channel为非阻塞模式**
*/
serverSocketChannel.configureBlocking(false);
/**
* 5.将channel注册到selector上,监听连接事件
*/
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功!");
/**
* 6.循环等待接入的连接
*/
for (; ; ) {
//while(true) c for;;
/**
* 获取可用channel数量
*/
int readyChannels = selector.select();
if (readyChannels == 0) continue;
/**
* 获取可用channel的集合
*/
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator iterator = selectionKeys.iterator();