4.Netty框架-网络IO编程模板(NIO编程模型)

一、什么是NIO? 与BIO有哪些区别?

1.什么是NIO?

        1、NIO = Selector+Channel+Buffer=构建Reactor模型。

        2、非阻塞IO,对应的IO模型是 多路复用IO。

       NIO: 同步非阻塞式IO,服务器实现模式为多个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 

        NIO 是一种同步非阻塞的 IO 模型。

        1)同步是指线程(多路复用器)不断轮询 IO 事件是否就绪,非阻塞是指线程在等待 IO 的时候,可以同时做其他任务。

        2)同步的核心就是 Selector,Selector 代替了线程本身轮询 IO 事件,避免了阻塞同时减少了不必要的线程消耗;

        3)非阻塞的核心就是通道和缓冲区,当 IO 事件就绪时,可以通过写道缓冲区,保证 IO 的成功,而无需线程阻塞式地等待。

        3、NIO = BUFFER + Selector  + Channel

        4、非阻塞= BUFFER + Channel;

        5、同步= Selector  ;

2.NIO和BIO的区别?

        1.OIO面向流(字节/字符),NIO面向缓冲区。流:要求顺序,缓冲区不必、

        2.OIO是阻塞的

        3.OIO没有选择器,NIO有。

            NIO《-》OIO

            Channel《-》Socket

           ServerChanel《-》ServerSocket

        BIO(accept、io 都是阻塞):同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 

二、NIO的基本组成:

        1.Channel:通道,互相通信的入口。

        2.Buffer:缓冲器,数据临时保存的地方。

        3.Selector:多路复用器,由系统提供,实现一个线程能够轮训多个通道的核心。

        1、Channel:

            FileChannel : 文件

            DatagramChanne : UDP

            SocketChannel : 与客户端建立产生的socket

            ServerSocketChannel : 服务端socket

    (1)FileChannel文件通道,用于文件的数据读写。

       //文件拷贝

        FileChannel inChannel = new FileInputStream(src).getChannel();

        FileChannel outChannel = new FileOutputStream(dst).getChannel();

        try {

            //从inChannel文件中读出count bytes ,并写入outChannel文件。

            inChannel.transferTo(0, inChannel.size(), outChannel);

        } finally {

            if (inChannel != null)

                inChannel.close();

            if (outChannel != null)

                outChannel.close();

        }

    (2)SocketChannel套接字通道,用于Socket套接字TCP连接的数据读写。

    (3)ServerSocketChannel服务器嵌套字通道(或服务器监听通道),允许我们监听TCP连接请求,为每个监听到的请求,创建一个SocketChannel套接字通道。、

    (4)DatagramChannel数据报通道,用于UDP协议的数据读写。

        2、BUFFER 缓冲器:
        BUFFER =  为什么说NIO是基于缓冲区的IO方式呢?因为,当一个链接建立完成后,IO的数据未必会马上到达,为了当数据到达时能够正确完成IO操作,在BIO(阻塞IO)中,等待IO的线程必须被阻塞,以全天候地执行IO操作。为了解决这种IO方式低效的问题,引入了缓冲区的概念,当数据到达时,可以预先被写入缓冲区,再由缓冲区交给线程,因此线程无需阻塞地等待IO。

        在 JDK 1. 4 中 新 加入 了 NIO( New Input/ Output) 类, 引入了一种基于通道和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆的 DirectByteBuffer 对象作为这块内存的引用进行操作,避免了在 Java 堆和 Native 堆中来回复制数据。

        2.1、通道的读取:就是将数据从通道读取到缓冲区中;通道的写入,就是将数据从缓冲区中写入到通道中。

        NIO的Buffer(缓冲区)本质上是一个内存块,既可以写入数据,也可以从中读取数据。

        NIO的Buffer类,是一个抽象类,位于java.nio包中,其内部是一个内存块(数组)。

        NIO的Buffer与普通的内存块(Java数组)不同的是:NIO Buffer对象,提供了一组更加有效的方法,用来进行写入和读取的交替访问。

        需要强调的是:Buffer类是一个非线程安全类。

        2.2、Buffer的属性:

           位置(position):当前缓冲区(Buffer)的位置,将从该位置往后读或写数据。

           容量(capacity):缓冲区的总容量上限。

           上限(limit):缓冲区的实际容量大小。

       2.3、Buffer的分类:(除Boolean)

           ByteBuffer、

           CharBuffer、

           DoubleBuffer、

           FloatBuffer、

           IntBuffer、

           LongBuffer、

           ShortBuffer、

            MappedByteBuffer

       2.4、Buffer的原理:

     默认初始:写模式:position=0,limit=capacity

    1.在写入模式下,position的值变化规则如下:

        (1)在刚进入到写模式时,position值为0,表示当前的写入位置为从头开始。

        (2)每当一个数据写到缓冲区之后,position会向后移动到下一个可写的位置。

        (3)初始的position值为0,最大可写值position为limit-1。当position值达到limit时,缓冲区就已经无空间可写了。

    2.flip()翻转后limit=position,position=0

    3.在读模式下,position的值变化规则如下:

        (1)当缓冲区刚开始进入到读模式时,position会被重置为0。

        (2)当从缓冲区读取时,也是从position位置开始读。读取数据后,position向前移动到下一个可读的位置。

        (3)position最大的值为最大可读上限limit,当position达到limit时,表明缓冲区已经无数据可读。

    数据写入后,如果要从缓冲区读取数据,这就要进行模式的切换,可以使用(即调用)flip翻转方法,将缓冲区变成读取模式。

   3、Selector多路复用器:

       依赖底层的epoll/select , JavaSelector选择器可以监听多个文件描述符(一个网络连接系统底层使用一个文件描述符表示),实现IO多路复用。

       实现IO多路复用,从具体的开发层面来说,首先把通道注册到选择器中,然后通过选择器内部的机制,可以查询(select)这些注册的通道是否有已经就绪的IO事件(例如可读、可写、网络连接完成等)。

三、NIO的编程模板:

    1、NIO编程服务端时序图:

2、NIO编程服务端步骤:

你可能感兴趣的:(4.Netty框架-网络IO编程模板(NIO编程模型))