NIO网络编程初学

****文章内容知识来自“慕课网讲师 张小喜”——《解锁网络编程之NIO的前世今生》****

****本人仅做学习笔记使用****

NIO网络编程初学

一、NIO网络编程模型

编程模型——对编程共性的抽象——把动物装冰箱

例:🐘把大象装冰箱:打开冰箱——放入大象——关上冰箱

       🐅把老虎装冰箱:打开冰箱——放入老虎——关上冰箱

1、BIO

编程模型:

由阻塞式I/O引起的3个缺点:

  1. 阻塞式I/O模型——体现在服务器端线程阻塞等待客户端发起请求

  2. 弹性伸缩能力差——体现在一个客户端对应一个服务器端线程

  3. 多线程耗资源——线程创建、销毁、CPU调度

2、NIO

编程模型:

相比于BIO模型改进的地方:

  1. 非阻塞式I/O模型——服务器端提供一个单线程的Selector统一管理客户端的连接

  2. 弹性伸缩能力强——服务器端采用单线程处理所有客户端请求

  3. 单线程节省资源——不需要频繁创建、销毁线程,没有线程上下文切换

二、NIO网络编程详解

核心API:通道(Channel)、缓冲区(Buffer)、选择器或多路复用器(Selector)、选择键(SelectionKey)

1、通道(Channel

特性🤖:

  1. 双向性——支持双向传输,即可读又可写

  2. 非阻塞性——可工作在非阻塞模式下(此特性构成NIO网络编程的基础)

  3. 操作唯一性——只能通过操作Buffer来对Channel进行读写操作

实现👻:

  1. 文件类——FileChannel------------用于对文件进行读写操作📄

  2. UDP类——DatagramChannel----------用于对UDP数据的读写操作📃

  3. TCP类——ServerSocketChannel/ SocketChannel🧾

TCP类Channel使用(部分代码片段):

/**
 *代码片段1. 服务器端 通过ServerSocketChannel创建channel通道
 */
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
/**
 * 代码片段2. 服务器端 为channel通道绑定监听端口
 */
serverSocketChannel.bind(new InetSocketAddress(8000));
/**
 * 代码片段3.服务器端 设置channel为非阻塞模式
 */
serverSocketChannel.configureBlocking(false);
/**
 * 代码片段4.服务器端 监听客户端连接,建立socketChannel连接
 */
SocketChannel socketChannel = serverSocketChannel.accept();
/**
 * 代码片段5. 客户端 建立与服务器端的连接
 */
SocketChannel socketChannel = SocketChannel.open
        (new InetSocketAddress("127.0.0.1", 8000));

2、缓冲区(Buffer)

特性🎮:

  1. 作用:读写Channel中数据————只能通过Buffer对Channel进行操作

  2. 本质:一块内存区域————被NIO包装成NIOBuffer对象,并提供一系列方法便于操作此内存

属性👑:

(以byteBuffer举例,相当于一个byte类型的数组)

  1. Capacity(容量):标明数组最大可容纳多少字节

  2. Position(位置):

    写模式下: 表示当前位置,数据写入后,会向后移动到下一个可插入数据的buffer单元;初始为0,最大值为容量-1

    读模式下: 切换到读模式时,会被重置为0,读取数据后,将向后移动到下一个可读数据位置

  3. Limit(上限):

    写模式下: 表示最多可向Buffer中写入多少数据,此模式下等于Capacity

    读模式下: 切换到读模式时,表示最多能从Buffer中读取多少数据,此时会被设置成写模式下的Position值

  4. Mark(标记):存储一个特定的Position位置,之后可通过调用Buffer的reset()方法来恢复到这个Position位置,从该位置开始处理数据

用法🎨:

/**
 * 初始化长度为10的byte类型的buffer
 */
ByteBuffer byteBuffer=ByteBuffer.allocate(10);

/** 
* 向byteBuffer中写入三个字节 
*/ 
byteBuffer.put("abc".getBytes(Charset.forName("UTF-8")));

/**
 * 将byteBuffer从写模式切换为读模式
 */
byteBuffer.flip();

/**
 * 从byteBuffer中读取一个字节
 */
byteBuffer.get();

/**
 * 调用mark()方法记录当前position位置
 */
byteBuffer.mark();

/**
 * 先调用get方法读取到下一个字节
 * 再调用reset方法将position重置到mark位置
 */
byteBuffer.get();
byteBuffer.reset();

/**
 * 调用clear方法重置所有属性
 */
byteBuffer.clear();

3、多路复用器(Selector)

  1. 作用🎯 :I/O就绪选择--------能够检测一到多个NIO通道,并知晓通道是否做好读写准备;通过Selector,一个单线程就可以管理多个Channel,从而管理多个网络连接

  2. 地位🔫 :NIO网络编程的基础---------NIO网络编程是基于Selector非阻塞式I/O之上的

     Selector使用(部分代码片段):

/**
*代码片段1. 创建Selector
*/
Selector selector = Selector.open();
/**
*代码片段2. 将channel注册到selector上,监听可读就绪事件
*/
SelectionKey selectionKey = channel.register(selector,SelectionKey.OP_READ);
/**
*代码片段3. 阻塞等待channel是否有就绪事件发生,返回就绪channel数量
*/
int selectNum = selector.select();
/**
*代码片段4. 获取发生就绪事件的channel集合
*/
Set<SelectionKey> selectionKeys = selector.selectedKeys();

4、选择键(SelectionKey)

  1. 四种就绪状态常量:

    • OP_CONNECT(连接就绪)

    • OP_ACCEPT(接收就绪)

    • OP_READ(读就绪)

    • OP_WRITE(写就绪)

  2. 有价值的属性:

    调用selector对象的selectedKeys()方法时,会返回一个SelectionKey类型的集合

    /**
    * 通过selectionKeys集合可获取到可用channel集合
    */
    Set<SelectionKey> selectionKeys = selector.selectedKeys();

NIO编程实现步骤

  • 第一步:创建Selector

  • 第二步:创建ServerSocketChannel,并绑定监听端口

  • 第三步:将Channel设置为非阻塞模式

  • 第四步:将Channel注册到Selector上,监听连接事件

  • 第五步:循环调用Selector的select()方法,检测就绪情况

  • 第六步:调用selectedKeys()方法获取就绪channel集合

  • 第七步:判断就绪事件种类,根据状态调用对应业务处理方法

  • 第八步:根据业务需要决定是否再次注册监听事件,重复执行第三步操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值