网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

点击上方\”java全栈技术\”关注网络编程,每天学习一个java知识点

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

引言java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO),为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

目录大纲1.阻塞和非阻塞

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

2.同步和异步

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

3.Java IO模型,NIO,BIO,AIO

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

4.NIO的原理

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

5.NIO操作流程

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

6.代码演示

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

1.阻塞和非阻塞阻塞和非阻塞是进程在访问数据的时候,进程需不需要等待。

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

1. 阻塞

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

当数据没有准备好时,都会一直等待缓冲区中的数据准备就绪之后才会开始处理,否则会一直等待下去。

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

2. 非阻塞

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

当进程访问到数据缓冲区时,如果数据还未准备好,会直接返回不会一直等待,如果数据已经准备好了,也会直接返回。

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

2.同步和异步同步和异步都是基于应用程序和操作系统处理IO事件锁采用的方式。

网络编程-「每日分享」网络编程-NIO、BIO、AIO详解

同步:

1. 同步是应用系统直接参与IO读写操作。在处理IO事件的时候必须阻塞在某个方法上面等待IO事件完成(阻塞IO事件或则通过轮询IO事件的方式)。

2. 阻塞IO实现方式,一般是直接阻塞到read和write方法。都是将读(写)方法交给线程来操作,然后阻塞线程的方式来实现,只是这样对线程开销较大。

异步:

1. 异步是所有的IO读写都交给了操作系统,这个时候就可以去做其它的事情并不需要去完成真正的IO操作,当操作完成IO后,系统将会给的应用程序一个通知的。

3.Java IO模型,NIO,BIO,AIONIO:

jdk1.4 linux多路复用技术 (select模式)实现IO事件的轮询方式同步非阻塞的模式,这种方式目前是主流的网络通信模式。

目前市面上的这种模式的框架有:Mina, netty,mina2.0,nett5.0–网络通信框架比直接写

NIO要容易些,并且代码可读性更好。

BIO:

JDK1.4以前使用都是BIO阻塞IO,主要是阻塞到线程来操作的,但对于线程的开销本来就是性能的浪费。

AIO:

jdk1.7(NIO2)才是实现真正的异步aio,学习 它的思想主要是借鉴了linux epoll模式。

4.NIO的原理先来看一张图

网络通信中,NIO也提供了SocketChannel和ServerSocketChannel两种不同的套接字通道来实现,这两个类都实现了Channel接口。它们可以设置阻塞与非阻塞两种模式,为了实现高负载高并发都采取非阻塞的模式。

NIO采用缓冲区Buffer,实现对数据的读写操作,缓冲区是固定大小,并由内部状态记录有多少数据被放入或者取出。

与阻塞IO不同,阻塞IO采用阻塞式流(Stream)的方式进行读写,流是单向的只能向一个方向读数据或者写数据。

而通道是双向的,可以同时在通道上发送和读取数据,而且是非阻塞的,在没有数据可读可写时可以去做别的事情。

主要使用了ServerSocketChannel,SocketChannel,Selector,ByteBuffer这么几个类。

1.ServerSocketChannel(服务端使用类)

采用api文档解释:通过调用此类的 open 方法创建服务器套接字通道。新创建的服务器套接字通道已打开,但尚未绑定。

试图调用未绑定的服务器套接字通道的 accept 方法会导致抛出 NotYetBoundException。

可通过调用相关服务器套接字的某个 bind 方法来绑定服务器套接字通道。多个并发线程可安全地使用服务器套接字通道。

2.SocketChannel(客户端使用类)

采用api文档解释:通过调用此类的某个 open 方法创建套接字通道。

新创建的套接字通道已打开,但尚未连接。试图在未连接的通道上调用 I/O 操作将导致抛出 NotYetConnectedException。

可通过调用套接字通道的 connect 方法连接该通道;一旦连接后,关闭套接字通道之前它会一直保持已连接状态。

可通过调用套接字通道的 isConnected 方法来确定套接字通道是否已连接。

3. Selector(选择器):

是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector可使一个单独的线程管理多个 Channel,selector 是非阻塞 IO 的核心。

当通道使用register(Selector sel, int ops)方法将通道注册选择器时,选择器对通道事件进行监听,通过第二个参数指定监听的事件类型。

其中可监听的事件类型包括以下:

读 : SelectionKey.OP_READ (1)

写 : SelectionKey.OP_WRITE (4)

连接 : SelectionKey.OP_CONNECT (8)

接收 : SelectionKey.OP_ACCEPT (16)

如果需要监听多个事件是:

int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE ; //表示同时监听读写操作

4.Bytebuffer

ByteBuffer类是Buffer的子类,Buffer是顶层抽象类,ByteBuffer继承Buffer,也是抽象类。看看继承结构。

ByteBuffer是在javaNIO中常使用的一个缓冲区类,使用ByteBuffer可以进行高效的IO操作。通过 ByteBuffer提供很多读写的方法put(),get(),并且还包含四个很重要的属性。

容量(capacity)

capacity指的是缓冲区能够容纳元素的最大数量,这个值在缓冲区创建时被设定,而且不能够改变,如下,我们创建了一个最大容量为10的字节缓冲区;

ByteBuffer bf = ByteBuffer.allocate(10);

上界(limit)

limit指的是缓冲区中第一个不能读写的元素的数组下标索引,也可以认为是缓冲区中实际元素的数量;

位置(position)

position指的是下一个要被读写的元素的数组下标索引,该值会随get()和put()的调用自动更新;

标记(mark)

一个备忘位置,调用mark()方法的话,mark值将存储当前position的值,等下次调用reset()方法时,会设定position的值为之前的标记值;

四个属性值之间的关系

根据以上四个属性的定义,我们可以总结出它们之间的关系如下:

0 <= mark <= position <= limit <= capacity

5.NIO操作流程1. 服务端对象:ServerSocketChannel

2. 客户端对象:SocketChannel

3. 选择器:Selector selector= Selector.open();//这样就打开了选择器

4. 获得选择器中的事件集合:Set<SelectionKey> key= selector.selectedKeys()

5. Selectionkey:可以通过它来判断IO事件是否已经就绪

key. isAccptable:是否可以接受客户端的连接

key, isConnctionable:是否可以连接服务端

key, isReadableo:缓冲区是否可读

key, isWriteableo:缓冲区是否可写

6.如何注册

channel.regist(selector, Selectionkey.OP_WRITE)//注册写事件

channel.regist(Selector, Selectionkey.OP_READ);//注册读事件

channel.regist(Selector, Selectionkey.OP_CONNECT);//注册连接事件

channel.regist(Selector, Selectionkey.OP_ACCEPT);//注册请求事件

以上注册成功之后就可以通过SelectionKey来判断io事件是否就绪,然后可以进行后续操作。

6.代码演示现在来演示一下网络编程中的nio使用,使用网络编程nio的编程就需要使用到Channel(管道)、Selector(事件选择器) 、Bytebuffer(缓冲区)。

演示代码一般会使用服务端代码和客户端代码分别书写。我会尽量在代码中把注释写详细一些。

1.服务端代码

2.客户端代码

先运行服务端程序会显示“服务器已经开启”的字样,然后运行客户端程序会在连接成功时发送\”我是客户端来了\”的字样,服务端就会接收到客户端的数据并且打印。

然后客户端输入“111”,紧接着服务端就会打印“服务端接收客户端传过来的数据:客户端输入数据为:111”的字样,然后在客户端继续输入222,服务端就会打印出“服务端接收客户端传过来的数据:客户端输入数据为:222”

如下:

服务端显示:

服务器已经开启…服务端接收客户端传过来的数据:我是客户端来了服务端接收客户端传过来的数据:客户端输入数据为:111服务端接收客户端传过来的数据:客户端输入数据为:222客户端显示

我是服务器

111

我是服务器

222

我是服务器

原创猿程之家

本文来自网络,不代表唯米智能立场,转载请注明出处。如有侵权请联系删除。http://www.weiseo.cc/b/3321.html

作者: 小易

上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 2013723@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部
在线客服系统