本文根据《Netty权威指南(第2版)》第2章关于时间服务器的demo程序,概括地描述各种IO的应用,站在更宏观的角度看清差异。
目录
一. 传统的BIO
1. 时间服务器的设计
2. 问题
二. 伪异步I/O编程
1. 时间服务器的设计
2. 问题
三. NIO编程
1. JDK的NIO
2. 时间服务器的设计
四、AIO编程
1. JDK的AIO
2. 时间服务器的设计
(1)客户端
① 构建Socket(阻塞,直到与服务器建立连接)
② 通过socket获取输出流、写入请求信息
③ 通过socket获取输入流、读出响应信息(阻塞,直到读取到指定大小or指定结束符)
(2)服务端
① 构建ServerSocket
② 监听请求(阻塞,直到读取到客户端请求)
③ 监听到请求,创建Socket
④ 创建线程处理请求:通过socket获取输入流,读取请求信息 => 通过socket获取输出流,写入响应信息
1个线程只能处理1个客户端连接,无法满足高性能、高并发接入场景
在服务端引入“线程池”
如果发送方较慢或网络传输较慢,读取方将被阻塞;如果读取方处理较慢,TCP的窗口size↓,直到为0,发送方将被阻塞。阻塞时间取决于对方I/O线程的处理速度和网络I/O的传输速度。
NIO = New I/O = Non-block I/O
与Socket、ServerSocket对应的是SocketChannel、ServerSocketChannel。严格讲,只是非阻塞I/O,不是异步的。
(1)缓冲区Buffer:实质是一个数组,读(写)NIO中的数据是从缓存区读(写)的
(2)通道Channel:可以用于读or写or同时进行两者,流只是在一个方向上移动(流是InputStream或OutputStream的子类)
(3)多路复用器Selector:Channel注册在Selector上,Selector通过selectedKeys()方法轮询已就绪的Channel(有读or写事件发生的Channel)
JDK 1.5update10之前,Selector基于select/poll实现
JDK 1.5update10之后,Selector基于epoll实现,没有连接句柄数的限制,意味着只需要1个Selector线程即可处理成千上万的客户端连接。
AIO = NIO 2.0
NIO 2.0的异步套接字通道是真正的异步非阻塞I/O,不需要通过selector对注册的通道进行轮询即可实现异步读写;
异步通道是由JDK底层的线程池负责回调并驱动读写操作。