Java-----网络编程2
Posted 小鹿可可乐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-----网络编程2相关的知识,希望对你有一定的参考价值。
1.IO模型
1.1 同步/异步(基于应用程序与操作系统处理IO事件)
- 同步:是指用户程序直接参与IO操作过程
- 异步:指所有的数据由操作系统完成,然后通知应用程序
1.2 阻塞/非阻塞(进程在访问数据的时候,数据是否准备就绪)
- 阻塞:需要等待缓存区的数据准备好才能访问,如果数据没有准备好则一直等待
- 非阻塞:访问数据的时候,如果数据没准备好会直接返回,如果准备好,直接返回
1.3 常见IO模型
- 阻塞IO
- 非阻塞IO
- IO复用
- 信号驱动IO
- 异步IO
2.BIO:同步阻塞
2.1 Socked通信流程
2.1.1服务端
- 创建ServerSocket实例,并绑定端口
- 通过accept监听并接受客户端的连接上的socket
- 服务端通过socket和客户端进行读写操作
- 关闭socket资源
2.1.2 客户端
- 创建socket实例并通过Connection连接服务端
- 和服务端进行读写操作
- 关闭资源
2.2 阻塞体现?
accept()、read()、write()、connection()
2.3 应用场景
客户端连接数量少且固定的场景
3.NIO:同步非阻塞
3.1 NIO编程流程
3.1.1 服务端
1、实例化通道:ServerSocketChannel
2、绑定端口:通过 ServerSocketChannel调用bind()方法帮定端口
3、将ServerSocketChannel设置为非阻塞
4、实例化选择器(IO复用器)Selector
5、将ServerSocketChannel注册给选择器,并且关注accept事件
6、监听事件是否完成:selector.select(),如事件未完成则一直阻塞直至事件完成
7、获取已完成事件的集合并遍历,判断是否是accept事件事件,是:则进行accept()调用,获取SocketChannel
8、设置SocketChannel为非阻塞,并将SocketChannel注册到selector选择器,并关注read事件
9、监听事件是否完成,若有时间完成,则判断是否是read读事件
10、通过SocketChannel通道来读取数据(Buffer),读完数据循环值事件监听,即步骤6
11、关闭资源:SocketChannel、Selector、 ServerSocketChannel
3.1.2 客户端
1、实例化通道:SocketChannel
2、设置 SocketChannel为非阻塞
3、实例化复用器:Selector
4、连接服务端connect(),(该方法会直接返回不会阻塞,返回是Boolean,是否是连接成功)
5、若连接返回为false,则将SocketChannel注册到复用器中,并监听connect可连接事件
6、监听复用器中事件是否完成(Selector.select),若完成则判断完成集合中是否是可连接事件 将可连接事件完成(channel.finishConnect())
7、给服务端发送消息,channel.write()操作
8、关闭资源:selector、SocketChannel
3.2 NIO提供新组件
selector:复用器
将用户关注的事件(4种)交给复用器,内核就来帮助用户关注事件是否完成,将完成事件结果告诉用户,复用器是依赖于系统
channel:通道
通道:主要是和IO进行连接,数据的操作需要借助Buffer缓冲处理
serverSocketchannel:TCP连接中用户服务端接收客户端的连接
socketchanel:TCP连接中用户连接服务端
buffer:缓冲区
缓冲区:数据的读取和写入通过Buffer和channel进行交互
3.3 selector:复用器
3.3.1 介绍
selector一般称作选择器,也叫做多路复用器作用是检查一个或者多个NIO Channel(通道)的状态是否处于可读、可写。。。,可以实现单线程管理多个channels,也可以管理多个网络请求
3.3.2 使用步骤
- 创建selector实例Selector.open()
- 非阻塞的channel注册到Selector实例中severSocketChannel.register(selector,SelectionKey.OP_READ)
- 通过选择器实例来监听事件是否完成selector.select()
- 遍历感兴趣事件集合selector.selectedKeys().iterator()判断是可读、可接受等事件分别做处理
- 如果还有关注事件,则跳转到第3不继续监听
- 最终关闭选择器
3.3.3 selector选择过程
在内部维护了三个集合
- 已注册的键的集合(Registered key set):所有与选择器关联的通道所生成的键的集合称为已经注册的键的集合。并不是所有注册过的键都仍然有效。这个集合通过 keys()方法返回,并且可能是空的。这个已注册的键的集合不是可以直接修改的;试图这么做的话将引发java.lang.UnsupportedOperationException。
- 已选择的键的集合(Selected key set):已注册的键的集合的子集,这个集合的每个成员都是关联的通道被选择器(在前一个选择操作中)判断为已经准备好的,并且包含键的的interest集合中的操作,这个集合通过selectdKeys()方法返回,并且有可能是空的,不要将已选择间的集合与ready集合混淆,这是一个键的集合,每个键都关联一个已经准备好至少一种操作的通道,每个键都有一个内嵌的ready集合,知识了所关联的通道已经准备好的操作
- 已取消的键的集合(Cancelled key set) :已注册的键的集合的子集,这个集合包含了 cancel() 方法被调用过的键(这个键已经被无效化),但它们还没有被注销。这个集合是选择器对象的私有成员,因而无法直接访问。
select()过程
- 已取消的键的集合将被检查。如果非空,每个被取消的键的集合将从其他两个集合中移除,并且相关通道将被注销,该步骤后,已取消集合将是空的
- 已注册的键的集合汇总的键的interest集合将被检查,该步骤的检查执行后,对interest集合的改动不会影响剩余的检查过程一旦就绪事件被确定下来了,底层操作系统将会被查询,来确定底层操作系统真是就绪状态,依赖特定的select()方法调用,如果没有通道准备好,线程将被阻塞在这里,通常会有超时值,直到操作系统调用完成为止,这个过程可能会使调用线程睡眠一段时间,然后当前每个通道的就绪时间将被确定下来,对于那些没有准备好的通道将不执行任何操作,对于那些系统指示至少已经准备好interest集合中的一种操作的通道,将执行以下两种操作中的一种:
a.如果通道的键还没有处于已选择的键的集合中,那么键的ready集合将被清空,然后表示操作系统发现的当前通道已经准备好的操作系统的比特掩码将被设置
b.否则,也就是键在已选择的键的集合中,键的ready集合将被表示操作系统发现的当前已经准备好的操作系统的比特掩码更新。所以之前的已经不再是就绪状态的操作不会被清除,事实上,所有的比特为位都不会被清除,有操作系统决定的ready集合是与之前的ready集合按位分离的,一旦键被放置与选择器的已选择的键的集合中,他的ready集合将是积累的,比特位只会被设置,不会被清理 - 步骤2可能耗费较长,特别激发的线程处于休眠状态是,与该选择器相关的键可能被同时取消,当步骤2结束时,步骤1将重新执行,以完成任意一个在选择进行的过程中,借鉴可能已经被取消的通道注销
- select操作的返回值是ready集合在步骤2中被修改的键的数量,而不是已选择的键的集合中的通道的总数,返回值不是已准备好的通道的总数,而是从上一个select()调用之后进入就绪状态的通道的数量,之前的调用中就绪的,并且在本次调用中任然就绪的通道将不会被计入,而那些在前一次的调用中已经就绪但已经不再处于就绪状态的通道也不会被计入,这些通道可能已经在已选择的键的集合中,但不会被计入返回值中,返回值可能是0
3.3.4 select()方法介绍
- int select():阻塞到至少有一个通道上注册的事件就绪
- int select(long timeout):也是则塞等到事件就绪,最长等待时间为timeout
- int selectNow():非阻塞,只要有通道就绪立即返回
3.3.5 停止选择方法
wakeup():使处于还没有返回的选择操作立即返回
close():使处于阻塞的选择操作会立即唤醒,并且将注册到选择器上的channel注销,所有的键被取消
3.4 NIO 应用场景
适用于高并发量且业务相对简答场景:QQ、微信
4. AIO:异步非阻塞
应用场景:使用于连接数目多且连接比较长(重操作)的架构
今天也要好好学习呀~
以上是关于Java-----网络编程2的主要内容,如果未能解决你的问题,请参考以下文章