前言
本系列为 Netty 学习笔记,本篇介绍总结Java NIO 网络编程。Netty 作为一个异步的、事件驱动的网络应用程序框架,也是基于NIO的客户、服务器端的编程框架。其对 Java NIO 底层 API 进行了封装,因此有必要对 Java 网络编程做个大概了解。本篇将重点放在 NIO 网络编程模型上,对 BIO 及 AIO 仅做简要说明;
1. Java 网络编程
- 最早期的 Java API(java.net)只支持由本地系统套接字库提供的阻塞函数,其弊端有:一个线程只能处理一条连接;在任何时候都可能有大量线程处于休眠状态,可能造成资源浪费;需要为每个线程的调用栈分配内存;上下文切换带来的开销会很麻烦;
- 2002年,JDK 1.4 在 java.nio 包中引入非阻塞 IO(NIO)。使用事件通知 API 以确定在一组非阻塞套接字中有哪些已经就绪能够进行 IO 相关的操作;
- 非阻塞 IO 的优势有:使用较少线程便可处理许多连接,减少了内存管理和上下文切换带来的开销;没有 IO 操作需要处理时,线程可以被用于其他任务;
- Java 支持3中网络编程模式 :BIO(同步阻塞型)、NIO(同步非阻塞型)、AIO(异步非阻塞型);BIO:适用于连接数目较小且固定的架构;NIO:适用于链接数量多且连接比较短的架构;AIO:适用于连接数目多且连接比较长的架构;
- BIO 以流的方式处理书局,NIO 以块的方式处理书局,块 IO 的效率比流 IO 高很多;
1.1 Javs NIO 基本介绍
- NIO 的三大核心部分部分:Channel(通道)、Buffer(缓冲区)、Selector(选择器);每个 Channel 都会对应一个 Buffer;Selector 对应一个线程,一个线程对应多个 Channel;多个 Channel 可以注册到一个 Selector;程序切换到哪个 Channel 由事件 Event 决定;Selector 会根据不同的事件,在各个通道上切换;Buffer 就是一个内存块,底层是一个数组;数据的读取和写入通过 Buffer,与 BIO 不同。BIO 要么是输入流,要么是输出流,不能双向,而 NIO 的 Buffer 是双向的;Channel 也是双向的,可以反映底层操作系统的情况;底层的操作系统通道就是双向的;
- NIO 是面向缓冲区,或者面向块编程的;
- NIO 可以做到用一个线程来处理多个操作;
- HTTP 2.0 使用了多路复用技术,做到同一个连接并发处理多个请求;
1.2 缓冲区 Buffer
- 缓冲区本质是一个可以读写的内存块,可以理解成一个容器对象,该对象提供一组方法,可以更轻松地使用内存块;
- 缓冲期内置了一些机制,能够跟踪和记录缓冲区的状态变化情况;
- Channel 提供从文件、网络读取数据的通道,但读取或写入的数据必须经由 Buffer;
- Buffer 有四个通用属性:capacity:容量,即可以容纳的最大数据量;在缓存区创建时被设定并且不能改变;limit:表示缓冲区当前的终点,不能对缓冲区中超过Limit的部分进行读写(相当于哨兵)。而且Limi