简单记录 慕课网-解锁网络编程之NIO的前世今生 & 一站式学习Java网络编程 全面理解BIO/NIO/AIO

内容概览

NIO是很重要的 网络编程

1、【了解】 NIO网络编程模型

1.1、NIO简介

  • 姓名:Non-blocking I/O 或 New I/O

    非阻塞IO

  • 出生:JDK 1.4

    JDK 1.4 及以上版本里提供的新API(New IO)

  • 职务:高并发网络服务器支持岗

    高性能和高并发场景使用

NIO是全新的输入输出标准库,作为原始I/O的补充。

IO和NIO的区别

原有的 IO 是面向流的、阻塞的,NIO 是面向块的、非阻塞的。

1.2、编程模型

  • 模型:对事物共性的抽象

  • 编程模型:对编程共性的抽象

    实际的问题 具体的解决方案 抽象出一套

    依靠这个模型解决这一类的问题

BIO编程模型

NIO编程模型



AIO 编程模型

1.3、网络编程三剑客 BIO & NIO & AIO

网络编程三剑客 BIO & NIO & AIO

始于BIO 陷于NIO 终于AIO

网络编程演进史 java.io

阻塞式编程BIO -> 非阻塞式编程NIO -> 异步编程AIO

BIO Java1.4以前 NIO Java 1.4 AIO Java 1.7

网络编程模型扎心三剑客,一直听说过BIO/NIO/AIO ,但未深入理解 过,实际的项目代码也未曾实现过。

为什么要学习网络编程模型呢?

  • 应用广泛 互联网大厂很多应用都是基于网络服务来实现的 。

  • 能接触到经典模式、经典代码 ,可用学习总结。

  • 业界、工作、面试,都会问到网络编程 ,要求熟悉TCP/IP、HTTP协议以及网络编程。

1.4、BIO是什么

BIO就是我们传统意义上的IO,它的特点是阻塞的。例如以前我们进行网络编程时,一个客户端使用一个线程来进行处理。这样会导致一个问题:服务器的线程数是有限制的,而不是每个客户端时时都有数据进行传输的。所以大量空的线程占了位置,但是又不工作,导致服务器的性能受限。

BIO和NIO对比:

BIO基于流,而NIO基于 Buffer. BIO 只能按照顺序读,而NIO可以随意读。

1.5、BIO网络模型

解决网络编程问题

基于阻塞IO实现的

  • 服务器启动:监听建立客户端的连接请求

  • 客户端启动:向服务器端发送建立连接请求

  • 服务端启动新线程: 服务器在接收到客户端的请求后,将会创建一个新的线程

  • 线程响应客户端: 服务端新创建的线程会与客户端建立socket连接,用于响应客户端的请求,通知客户端连接建立成功,随时可以发送数据。

  • 等待客户端再次发送请求:服务器端处理完客户端的请求之后,就会处于等待状态 可能一直等待中

服务器端为每一个客户端建立一个线程,一旦客户端请求过多,服务器端线程数量也会过多,服务器压里会变得过大 甚至是崩溃。 大量的并发

BIO网络模型缺点

  • 阻塞式I/O模型

    会导致服务器端的业务线程会因阻塞IO的问题一直阻塞等待客户端发起请求,如果客户端不发起请求,服务端的业务线程会一直存在。

    服务端一直等待客户端发送请求,对应的线程也一直存在。

  • 弹性伸缩能力差

    客户端与服务器端的线程数呈现1:1的关系, 如果是有很多客户端发送请求,对应的线程数也会有很多很多。

  • 多线程耗资源

    每一个线程都会对CPU的调度资源进行占用,一旦占用而不释放,则会导致资源的紧缺,甚至服务器的异常宕机、崩溃了。

    BIO的缺点是阻塞式I/O 引起的

1.6、NIO网络模型猜想

暂停一下,YY一波。

NIO,客户端的个数与服务器端的线程数呈M:1的关系

1.7、NIO网络模型

**第一步:**注册连接并提供服务:Selector 中初始化注册并建立连接事件,提供给Client建立连接的服务;

Client通过Selector连接与AcceptorHandler 发送创建客户端的连接,并又AcceptorHandler方法返回响应结果;同时该AcceptorHandler方法向Selector中注册可读事件(Client连接客户端成功后)。

**第二步:**提供服务:Client 发送请求,Selector中对注册状态及客户端可读性验证,正常情况下,已通过第一步,所以直接连接到处理器进行读写操作,根据需求执行业务逻辑,并响应给客户。

第三步:客户端连接可读,在向client响应客户端请求后,注册连接可读事件到Selector 中,所注册的是具体执行业务的Handler。

1.8、NIO网络模型改进

NIO网络模型改进改进优化

  • 非阻塞式I/O模型

    服务器端提供一个单线程的selector来统一管理所有客户端接入的连接,并负责监听每个连接所关心的事件。

  • 弹性伸缩能力强

    服务器端一个线程处理所有客户端的连接请求,客户端的个数与服务器端的线程数呈M比1的关系

    一个线程 处理所有请求。

  • 单线程节省资源

    避免了线程的频繁创建和销毁,同时也避免了多个线程之间上下文的切换,提高了执行效率

    线程创建、切换什么的都没了,节省了资源。

2、【熟悉】NIO网络编程详解

2.1、NIO核心类之Channel

NIO核心

  • Channel:通道
  • Buffer:缓冲区
  • Selector:选择器 或 多路复用器

Channel简介 Channel通道

  • 双向性
  • 非阻塞性
  • 操作唯一性

channel是信息传输的通道,是jdk NIO中对输入输出方法的另一种抽象,类比IO中的流,与流不同之处在于,channel具有双向性,而流是单向传输的,一个流必须是InputStream或OutputStream的子类,而通道可以用于读或写、二者也可同时进行。channel可以工作在非阻塞模式下,构成NIO的基础。在NIO中,操作channel的唯一方式是使用buffer,通过buffer操作channel,可实现数据块的传输。

Channel实现

  • 文件类:FileChannel

    用于对文件的读写

  • UDP类:DatagramChannel

    用于UDP数据读写

  • TCP类:ServerSocketChannel / SocketChannel

    TCP数据读写

数据读写

Socket回顾

Channel使用

2.2、NIO核心类之Buffer

Buffer简介 Buffer缓冲区

  • 作用:读写Channel中数据
  • 本质:一块内存区域

Buffer:缓冲区,它提供唯一与channel进行交互的方式,作用是读写channel中的数据。Buffer从本质上说是一块内存区域,它是一块可以写入数据,读取数据的内存。

Buffer属性

  • Capacity:容量

    分配的buffer容量,一旦写入的最大字节数超过这个容量,需要将其清空之后,才能继续往里面写数据的。

  • Position:位置

    范围0到容量-1

    当前操作的位置,初始值为0,最大值是容量值-1。

  • Limit:上限

    上限,写模式下等于Capacity,读模式下等于最多能读取的数据量。

  • Mark:标记

    标记,记录mark的位置,调用reset方法时,position会回到mark的位置。

操作

Buffer使用

/*
* 初始化长度为10的byte类型 buffer
*/
ByteBuffer.allocate(10);//allocate分配、指定的意思

 /*
* 向byteBuffer中写入三个字节
*/
byteBuffer.put("abc".getBytes(Charset.forName("UTF-8")));

 /*
* 将byteBuffer从写模式切换成读模式
*/
byteBuffer.flip()://flip

/**
* 从byteBuffer中读取一个字节
*/
byteBuffer.get();

/**
* 调用mark方法记录下当前position的位置
*/
byteBuffer.mark();

 /*
* 将b先调用get方法读取下一个字节
* 再调用reset方法将position重置到mark位置
*/
byteBuffer.get():
byteBuffer.reset();

/*
* 调用clear方法,将所有属性重置
*/
byteBuffer.clear();

数据读写

2.3、NIO核心类之Selector

Selector简介 选择器/多路复用器

  • 作用:I/O就绪选择
  • 地位:NIO网络编程的基础

Selector使用

最重要的应该就是代码片段3: 在这一步对就绪事件进行监听,如果一直不通过,就一直阻塞等待,直到有就绪事件发生,并注册通过检测有效,方才放行

SelectionKey 简介

  • 四种就绪状态常量

    连接就绪、接受就绪、读就绪、写就绪

  • 有价值的属性

NIO编程实现步骤

  • 第一步:创建Selector
  • 第二步:创建ServerSocketChannel,并绑定监听端口
  • 第三步将Channel设置为非阻塞模式
  • 第四步:将Channel注册到Selector上,监听连接事件
  • 第五步:循环调用Selector的select方法,检测就绪情况
  • 第六步:调用selectedKeys方法获取就绪channel集合
  • 第七步:判断就绪事件种类,调用不同业务处理方法
  • 第八步:根据业务需要决定是否再次注册监听事件,重复执行第四步操作

实战操作

3、【应用】NIO网络编程实战

服务器端功能实现

利用NIO编程知识,实现多人聊天室

服务器端业务处理功能实现

客户端功能实现 上

客户端功能实现 下

功能完善

NIO多人聊天室代码-https://github.com/liuawen/small-Project/tree/master/nio-chat-room

一个类运行多个实例

4、【掌握】NIO网络编程缺陷

缺陷分析

NIO网络编程缺陷

  • 麻烦:NIO类库和API繁杂

  • 心累:可靠性能力补齐,工作量和难度都非常大

    NIO网络编程实战中写的聊天室,Bug很多 测试

  • 有坑:Selector空轮询,导致CPU100%

    JDK 8 仍存在 发生概率低了点

5、【深谙】NIO总结

NIO网络编程原理与实战

5.1、NIO网络编程模型

5.2、NIO网络编程详解

通道(Channel)

简介 双向性 非阻塞性 操作唯一性

实现 文件类 FileChannel UDP类 DatagramChannel TCP类 ServerSocketChannel SocketChannel

用法

缓冲区(Buffer)

简介 读写Channel中数据 本质室一块内存区域

属性 容量 Capacity 上限 Limit 位置 Position 标记 Mark

用法

多路复用器(Selector)

简介 I/O事件就绪选择 NIO网络编程基础之一

用法

选择键(SelectionKey)

简介 四种就绪状态处理 有价值的属性

5.3、NIO网络编程实战

NIO编程实现步骤

  • 第一步:创建Selector
  • 第二步:创建ServerSocketChannel,并绑定监听端口
  • 第三步将Channel设置为非阻塞模式
  • 第四步:将Channel注册到Selector上,监听连接事件
  • 第五步:循环调用Selector的select方法,检测就绪情况
  • 第六步:调用selectedKeys方法获取就绪channel集合
  • 第七步:判断就绪事件种类,调用不同业务处理方法
  • 第八步:根据业务需要决定是否再次注册监听事件,重复执行第四步操作

写一波

5.4、NIO网络编程缺陷

NIO类库和API繁杂

可靠性能力补齐,工作量和难度非常大

Selector空轮询,CPU100%

NIO过于复杂

现在主流的网络通信是netty框架了,netty是常见的NIO框架

Netty是一个基于NIO的客户、服务器端的编程框架,是一个提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。使用Netty 可以快速简单地开发协议服务器和客户端等网络应用程序,Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。

官网:https://netty.io/

Github地址:https://github.com/netty/netty

Netty4.1

开发文档:https://netty.io/wiki/user-guide-for-4.x.html

API文档:https://netty.io/4.1/api/index.html

【Java】网络编程之NIO的更多相关文章

  1. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载.   ...

  2. Java网络编程之UDP

    Java网络编程之UDP 一.C/S架构中UDP网络通信流程 ①创建DatagramSocket与DatagramPacket对象 ②建立发送端,接收端 ③建立数据包 ④调用Socket的发送.接收方 ...

  3. Java网络编程之URLConnection

    Java网络编程之URLConnecton 一.URLConnection简介 URLConnection是一个抽象类,表示指向URL指定资源的活动连接.URLConnection有两个不同但相关的用 ...

  4. Java网络编程之URL和URI

    Java网络编程之URL与URI 一.URL与URI简介 URI = Universal Resource Identifier 统一资源标志符 URL = Universal Resource Lo ...

  5. Java网络编程之InetAddress浅析

    Java网络编程之InetAddress浅析 一.InetAddress综述 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetA ...

  6. Java网络编程之TCP

    Java网络编程之TCP ​ TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建 ...

  7. java网络编程之TCP通讯

    java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...

  8. 解锁网络编程之NIO的前世今生

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) NIO 内容概览: NIO 网络编程模型 NIO 网络编程详解 NIO 网络编程实战 NIO 网络编程缺 ...

  9. java网络编程之Socket编程

    概念 网络编程分为BIO(传统IO).NIO.AIO.Socket编程属于BIO这种传统IO. InetAddress java.net.InetAddress是JAVA中管理IP地址的类,常用 pu ...

随机推荐

  1. vue检查用户名是否重复

    前端函数如下,js方法代码无需更改,前端代码逻辑在components\common\lab_header.vue 只需要修改components\axios_api\http.js中调用的后端地址 ...

  2. 深入浅出java的Map

    HashMap的组成 首先了解数组和链表两个数据结构 1.数组 寻址容易,插入和删除元素困难 数组由于是紧凑连续存储,可以随机访问,通过索引快速找到对应元素,而且相对节约存储空间. 但正因为连续存储, ...

  3. Vue-router hash模式微信登录授权验证,#号处理

    微信授权登录验证会把网址中的#号去掉,这样在跳转的时候Vue拿不到Code.所以做了以下处理 let href = window.location.href; if (href.includes(&q ...

  4. vue第三单元(webpack的应用-能根据具体的需求构建对应的开发环境)

    第三单元(webpack的应用-能根据具体的需求构建对应的开发环境) #课程目标 理解什么是单页面应用. 掌握单页面和多页面的差异. 了解单页面的实现原理. 掌握模块化的方式实现webpack配置,区 ...

  5. (菜鸟都能看懂的)网络最大流最小割,Ford-Fulkerson及Dinic详解

    关于网络流: 1.定义 个人理解网络流的意思便是由一条条水管以及一个源点S一个汇点T和一些节点组成的一张图,现在要从S点流水到T点,问怎么流才能让流到T的流量最大.边权表示的是这条水管的最大流量,假设 ...

  6. Python-自动化测试面试

    1.以你做过的项目,举例来说一下你的自动化测试是怎么做的? 参考答案:就拿简历上的ecshop项目来说吧,在编写脚本前,我们会对系统进行评估,确认这个系统可不可以实现UI自动化,如果可以的话,就筛选出 ...

  7. Web服务器-服务器开发-返回浏览器需要的页面 (3.3.2)

    @ 目录 1.说明 2.代码 关于作者 1.说明 使用正则表达式,匹配客户端的请求头 获取到请求的路径 返回对应请求路径的文字 可以使用打开对应文件的方式去返回对应的文件 2.代码 from sock ...

  8. Qt QChart 创建图表

    Qt QChart 创建图表 @ 目录 Qt QChart 创建图表 效果 流程 代码 1. 饼图 2. 柱图 3. 折/曲线图 4. 区域图 效果 流程 graph LR q(value 数据) q ...

  9. 从零到一快速搭建个人博客网站(域名自动跳转www,二级域名使用)(二)

    前言 本篇文章是对上篇文章从零到一快速搭建个人博客网站(域名备案 + https免费证书)(一)的完善,比如域名自动跳转www.二级域名使用等. 域名自动跳转www 这里对上篇域名访问进行优化,首先支 ...

  10. 学习JUC源码(3)——Condition等待队列(源码分析结合图文理解)

    前言 在Java多线程中的wait/notify通信模式结尾就已经介绍过,Java线程之间有两种种等待/通知模式,在那篇博文中是利用Object监视器的方法(wait(),notify().notif ...