1.先解释同步和异步:
同步异步是一种通信机制。
同步:调用方需要保持等待直到I/O操作完成。
异步:调用方可以不用保持等待,只需要操作系统完成I/O操作通知调用方就可以了。
2.再说说阻塞和非阻塞:
阻塞非阻塞是一种调用机制。
阻塞:调用方等待I/O操作完成后才返回,就是阻塞的。
非阻塞:调用方不需要等待IO操作完成就立即返回。非阻塞的情况下,常常需要多次调用去check,才能获得IO操作的结果。
两个模型的区别在于对读时间的操作者。前者是用户程序自己执行读和写,后者是用户程序把缓冲区给了交给内核,内核读或写完成以后通知应用程序。
ACE是一个C++网络编程库,实现了Reactor 和 Proactor俩种模式。
Reactor:异步的方式编写代码,同步IO
Proactor:利用OS的异步IO而编写,是真正意义上的异步IO。
举个例子,将有助于理解Reactor与Proactor二者的差异,以读操作为例(类操作类似)。
在Reactor中实现读:
- 注册读就绪事件和相应的事件处理器
- 事件分离器等待事件
- 事件到来,激活分离器,分离器调用事件对应的处理器。
- 事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。
在Proactor中实现读:
- 处理器发起异步读操作(注意:操作系统必须支持异步IO)。在这种情况下,处理器无视IO就绪事件,它关注的是完成事件。
- 事件分离器等待操作完成事件
- 在分离器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操作完成。
- 事件分离器呼唤处理器。
- 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分离器。
可以看出,两个模式的相同点,都是对某个IO事件的事件通知(即告诉某个模块,这个IO操作可以进行或已经完成)。在结构上,两者也有相同点:demultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步),然后当条件满足时,就回调handler;不同点在于,异步情况下(Proactor),当回调handler时,表示IO操作已经完成;同步情况下(Reactor),回调handler时,表示IO设备可以进行某个操作(can read or can write)。
网络IO常见的为如下四中模型
1. blocking IO
2. nonblocking IO
3.IO multiplexing
4. asynchronous IO
最后,再举几个不是很恰当的例子来说明这四个IO Model:
有A,B,C,D四个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆;
B的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆;
C用的鱼竿和B差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;
D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发个短信。