• 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开始支持。

  • 相关阅读:
    VS Code 使用笔记
    Haskell语言开发工具
    Haskell语言学习笔记(81)Data.Typeable
    Haskell语言学习笔记(80)req
    Haskell语言学习笔记(79)lambda演算
    Haskell语言学习笔记(78)fix
    2733: [HNOI2012]永无乡
    牛课练习赛17
    bzoj3758. 数数
    【BZOJ1786】[Ahoi2008]Pair 配对
  • 原文地址:https://www.cnblogs.com/lzxulxy/p/12492900.html
Copyright © 2020-2023  润新知