1.模式介绍
在普通的事件处理机制:首先程序调用某个函数,然后函数执行,程序等待,当函数执行完毕后函数将结果和控制权返回给程序,最后程序继续处理。
Reactor模式的事件处理方式:我们可以将整个问题抽象。每个需要处理的事件就是一个事件源,每一个需要处理的事件接收到数据后的进一步处理操作作为一个事件处理器。我们将需要被处理的事件处理源及其事件处理器注册到一个类似于epoll的事件分离器中。事件分离器负责等待事件发生。一旦某个事件发送,事件分离器就将该事件传递给该事件注册的对应的处理器,最后由处理器负责完成事件的具体响应。
在Reactor模式中,应用程序不是主动的调用某个API完成处理,而是逆置了事件处理流程,应用程序需要提供相应的事件接口并注册到Reactor上,如果相应的事件发生,Reactor将主动调用应用程序注册的接口,通过注册的接口完成具体的事件处理。
2.模式组成
Reactor模式由事件源、事件反应器、事件分离器、事件处理器等组件组成。
事件源(handle):由操作系统提供,用于识别每一个事件,如Socket描述符、文件描述符等。在服务端系统中用一个整数表示。该事件可能来自外部,如来自客户端的连接请求、数据等。也可能来自内部,如定时器事件。
事件反应器(reactor):定义和应用程序控制事件调度,以及应用程序注册、删除事件处理器和相关描述符相关的接口。它是事件处理器的调度核心,使用事件分离器来等待事件的发生。一旦事件发生,反应器先是分离每个事件,然后调度具体事件的事件处理器中的回调函数处理事件。
事件分离器(demultiplexer):是一个有操作系统提供的I/O复用函数,在此我们选用epoll。用来等待一个或多个事件的发生。调用者将会被阻塞,直到分离器分离的描述符集上有事件发生。
事件处理器(even handler):事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供reactor在相应的事件发生时调用,执行相应的事件处理。一般每个具体的事件处理器总是会绑定一个有效的描述符句柄,用来识别事件和服务。
3.处理流程
分为两个部分,事件注册部分和事件分发部分 ;
在事件注册部分,应用程序首先将期待注册的套接字描述符作为事件源,并将描述符和该事件对应的事件处理回调函数封装到具体的事件处理器中,并将该事件处理器注册到事件反应器中。事件反应器接收到事件后,进行相应处理,并将注册信息再次注册到事件分离器epoll中。最后在epoll分离器中,通过epoll_ctl进行添加描述符及其事件,并层层返回注册结果。
在事件处理部分,首先事件反应器通过调用事件分离器的epoll_wait,使线程阻塞等待注册事件发生。此时如果某注册事件发生,epoll_wait将会返回,并将包含该注册事件在内的事件集返回给事件反应器。反应器接收到该事件后,根据该事件源找到该事件的事件处理器,并判断事件类型,根据事件类型在该事件处理器调用之前注册时封装的具体回调函数,在这个具体回调函数中完成事件处理。