NIO/IO

NIO/IO

一.IO

IO中的流只能是单向的

二.NIO的实现原理(jdk1.4)

NIO处理流程

(1)创建ServerSocketChannel, 配置它为非阻塞模式;
(2)绑定监听,配置TCP参数,例如backlog大小;
(3)创建一个独立的I/O线程,用于轮询多路复用器Selector;
(4)创建Selector, 将之前创建的ServerSocketChannel 注册到Selector. 上,监听
SelectionKey.ACCEPT;
(5)启动I/O线程,在循环体中执行Selector.select()方法, 轮询就绪的Channel;
(6)当轮询到了处于就绪状态的Channel时,需要对其进行判断,如果是OP_ACCEPT
状态,说明是新的客户端接入,则调用ServerSocketChannlaccept()方法接受新的客户端;
(7)设置新接入的客户端链路SocketChannel为非阻塞模式,配置其他的一些TCP参数;
(8)将SocketChannel注册到Selector, 监听OP_ READ操作位;
(9)如果轮询的Channel为OP_READ,则说明SocketChannel中有新的就绪的数据包
需要读取,则构造ByteBuffer对象,读取数据包;
(10)如果轮询的Channel为OP__WRITE,说明还有数据没有发送完成,需要继续发送990

以块的方式处理数据 ,Java NIO 由以下几个核心部分组成:

1)Channel

数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中 通道是可以双向的 。

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

2)Buffer

缓冲区:实质上是一个容器,一个连续的数组(通常指字节数组)。所有数据都通过 Buffer 对象来处理,写入到通道的所有对象都必须先放到缓冲区中;同样地,从通道中读取的任何数据都要先读到缓冲区中。

Buffer的核心参数

1.capacity 缓冲区数组的总长度

2.position 下一个要操作的数据元素的位置

3.limit 缓冲区数组中不可操作的下一个元素的位置,limit<=capacity

4.mark 用于记录当前 position 的前一个位置或者默认是 0

调用 mark() 时,它将记录当前 position 的前一个位置,当我们调用 reset 时,position 将恢复 mark 记录下来的值 。 当你把缓冲区的数局写入到管道中的时候,你需要调用flip()方法将Buffer从写模式切换到读模式,调用flip()方法会将position设回0,并将limit设置成之前position的值。

创建一个buffer------>存储数据(position)------->调用flip()( limit=position;position=0; )------->读取数据------->调用clear( position=0;而limit=capacity; )------->存储数据(循环)

NIO里实现的buffer类型

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

3)Selector

Selector.open() ----> SelectorProvider.provider() ----> WindowsSelectorProvider---->SelectorProviderImpl ---->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>不看了,这源码感觉看不完。也不知道到底想要啥.。。

Selector允许单线程处理多个 Channel。

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

NIO SelectionKey中定义的4种事件

1)SelectionKey.OP_ACCEPT —— 接收连接继续事件,表示服务器监听到了客户连接,服务器可以接收这个连接了

2)SelectionKey.OP_CONNECT —— 连接就绪事件,表示客户与服务器的连接已经建立成功

3)SelectionKey.OP_READ —— 读就绪事件,表示通道中已经有了可读的数据,可以执行读操作了(通道目前有数据,可以进行读操作了)

  1. SelectionKey.OP_WRITE —— 写就绪事件,表示已经可以向通道写数据了(通道目前可以用于写操作)

这里 注意,下面两种,SelectionKey.OP_READ ,SelectionKey.OP_WRITE ,

① 当向通道中注册SelectionKey.OP_READ事件后,如果客户端有向缓存中write数据,下次轮询时,则会 isReadable()=true;

② 当向通道中注册SelectionKey.OP_WRITE事件后,这时你会发现当前轮询线程中isWritable()一直为ture,如果不设置为其他事件

适用场景

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

原文地址:https://www.cnblogs.com/lzxulxy/p/12492900.html