Skip to content

网络IO类型

一、BIO

BIO连接是同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

优点:

  1. 模型简单

  2. 编码简单

缺点:

  1. 性能瓶颈,请求数和线程数是N:N的关系。(可以通过线程池优化,但是根源上资源利用不够均匀)

  2. 高并发的情况,CPU上下文切换损耗大。

web服务器tomcat7以前都是使用BIO,7之后使用NIO

二、阻塞/非阻塞和同步/异步

洗衣机洗衣服(无论是阻塞式IO还是非阻塞式IO,都是同步IO模型)

同步阻塞: 把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗完去晾衣服。(干等待,什么都不做)

同步非阻塞:把衣服丢到洗衣机洗,然后再客厅玩游戏,定时去阳台看洗衣机是不是洗洗完了。洗完再去晾

异步阻塞:(几乎没有次情况)

异步非阻塞:把衣服丢进洗衣机洗,然后去客厅玩游戏,洗完衣服以后自动晾衣服,晾完以后播放音乐通知你已经完毕。

三、5种IO模型

模型:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO和异步IO。前4种是同步IO,最后一种是异步IO。

网络IO,用户程序和内核的交互为基准进行讲解

IO操作分为两步:发起IO请求等待数据准备,实际IO操作。

同步须要主动读写数据,在读写数据的过程中还是会堵塞。

异步仅仅须要I/O操作完毕的通知。并不主动读写数据,由操作系统内核完毕数据的读写。

  1. 阻塞I/O:同步阻塞等待

  2. 非阻塞式I/O:同步调用的同时,可以做别的任务,但是需要实时监听返回的结果。

  3. I/O多路复用:

I/O多路复用的阻塞是在select,epoll这样的系统调用,没有阻塞在真正的I/O系统调用,如recvfrom进程受阻与select,等待可能多个套接口中的任一个变成可读。

IO多路复用使用两个系统调用(select和recvfrom)核心是可以同时处理多个connection,而不是更快,所以连接数不高的情况下,性能不一定比多线程+阻塞IO好。阻塞的时候是被select这个函数block, 而不是被socket阻塞的。

  1. 信号驱动IO:信号驱动I/O的意思就是我们现在不用傻等着了,也不用去轮询。而是让内核在数据就绪时,发送信号通知我们。即发送通知让系统准备数据,系统接收到消息以后立马返回结果,并异步的去准备数据,当数据准备好调用回调函数执行处理数据最后返回。

  2. 异步I/O(POSIX的aio_系列函数) Future-Listener机制:

I/O操作分成两步:

  1. 发起IO请求,等待数据准备

  2. 实际的IO操作,将数据从内核拷贝到进程中。

前四种IO模型都是同步IO操作,区别在于第一阶段,第二阶段都是一样的,在数据从内核复制到应用缓冲区期间(用户空间),进程堵塞于recvfrom调用或者select函数。相反,异步IO模型在这两个阶段都要处理。

阻塞IO和非阻塞IO的区别在于第一步,发起的IO请求是否会被阻塞,如果阻塞直到完成就是传统的阻塞IO,如果不阻塞就是非阻塞IO。

同步IO和异步IO的区别在于,第二步是否被阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,如果不阻塞,就是系统帮你完成了IO操作再将结果返回,就是异步IO。

核心点:

  • 阻塞非阻塞说的是线程的状态

  • 同步和异步说的是消息的通知机制

  • 同步需要主动读写数据,异步是不需要读写数据

  • 同步IO和异步IO是针对用户应用程序和内核交互

四、echo服务

echo服务是一个应答服务(回显服务器),客户端发送什么数据,服务器就响应对应的数据。

echo是一个非常有用于调试和检测是服务