Socket BIO NIO AIO 基本概念
1. Socket1.1. Socket是什么Socket又称套接字应用程序通常通过套接字向网络发出请求或者应答网络请求使主机间或者一台计算机上的进程间可以通讯。 当连接建立成功时服务端和客户端都会拥有一个Socket实例每个Socket实例都有一个InputStream和 OutputStream并通过这两个对象来交换数据。1.2. Socket工作机制主机A的应用程序要能和主机B的应用程序通信必须通过Socket建立连接而建立Socket连接必须由底层TCP/IP来建立TCP连接。 建立TCP连接需要底层IP来寻址网络中的主机。 网络层可以根据IP地址来找到目标主机目标主机上可能运行着多个应用程序通过TCP或UPD的地址也就是端口号来与指定的应用程序通信。 可以通过一个Socket实例来唯一代表一个主机上的应用程序的通信链路。1.3. Socket数据传输当连接已经建立成功时服务端和客户端都会拥有一个Socket实例每个Socket实例都有一个InputStream和OutputStream并通过这两个对象来交换数据。 当创建Socket对象时操作系统将会为InputStream和OutputStream分别分配一定大小的缓存区数据的写入和读取都是通过这个缓存区完成的。 写入端将数据写到OutputStream对应的SendQ队列中当队列填满时数据将被转移到另一端InputStream 的 RecvQ队列中 如果这时RecvQ已经满了那么OutputStream的write方法将会阻塞直到RecvQ队列有足够的空间容纳SendQ发送的数据。 这个缓存区的大小及写入端的速度和读取端的速度非常影响这个连接的数据传输效率, 由于可能会发生阻塞所以网络IO与磁盘I/O不同的是数据的写入和读取还要有一个协调的过程 如果在两边同时传送数据可能会产生死锁。2. 网络IO模型2.1. 同步IO和异步IO一个网络I/O读过程是数据从网卡→内核缓冲区→用户内存的过程。 同步:用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪。 异步:用户进程触发IO操作以后便开始做自己的事情而当IO操作已经完成的时候会得到系统内核的IO完成的通知。2.2. 阻塞IO和非阻塞IO用户程序发起IO操作会经历两阶段 第一阶段: 内核等待数据 第二阶段: 内核将数据从内核空间拷贝到用户空间 阻塞IO: 两阶段都阻塞 非阻塞IO: 内核等待数据阶段会直接返回异常码用户程序轮询查询内核数据准备情况 没有准备好直接返回异常码用户程序继续下一次轮询 准备好时用户轮询到来时内核将数据从内核空间拷贝到用户空间返回2.3. BIO(同步阻塞IO)应用程序发起IO请求后处理线程处于阻塞状态直到请求的IO数据从内核空间拷贝到用户空间。2.4. NIO(同步非阻塞IO)Java NIO 是Java 1.4版本引入的基于通道Channel和缓冲区Buffer进行操作采用非阻塞式 IO 操作允许线程在等待 IO 时执行其他任务。 应用程序发起IO请求后内核等待数据时会直接返回异常码 之后应用程序通过不断的轮询去检查请求数据是否已经完成 虽然在应用发起IO请求时无须阻塞。但在内核将数据拷贝到用户空间时还是会阻塞的为了保证数据的准确性和系统的安全稳定。2.4.1. IO多路复用在同步非阻塞IO模型下需要通过不断的轮询去检查请求数据是否已经完成这个过程是很耗CPU的。 因此便又诞生了I/O多路复用模型。 I/O多路复用模型使用操作系统提供的多路复用功能如 select、poll、epoll 等使得单个线程可以同时处理多个 I/O 事件。 当某个连接上的数据准备好时操作系统会通知应用程序。 这样应用程序可以在一个线程中处理多个并发连接而不需要为每个连接创建一个线程。2.5. AIO(异步非阻塞IO)AIO也就是NIO2.0 Java7中引入了NIO的改进版NIO2,它是异步IO模型。 异步IO则是采用“订阅-通知”模式即应用程序向操作系统注册IO监听然后继续做自己的事情。 当操作系统发生IO事件并且准备好数据后在主动通知应用程序触发相应的函数.参考Socket 学习笔记(一)ServerSocket与Socket入门详解Java IO 学习一同步/异步/阻塞/非阻塞如何理解IO模型中用户空间和内核空间