C++高性能服务框架revolver:base结构分析

来源:互联网 发布:bloodhound js 编辑:程序博客网 时间:2024/05/16 19:44

revolver基础库的结构图如下:


主要是三部分:reactor模块、关联组件模块、独立组件。

1.reactor

reactor模块主要是实现网络的分时复用设计的模块,可以在同一个线程模式下处理来自网络的读写事件、内部消息事件、定时器事件。以下是reactor的接口定义:
class CReactor{public:       ....voidset_message_processor(IMessageProcessor* proc){msg_proc_ = proc;};virtual int32_t open_reactor(uint32_t number_of_handlers) = 0;virtual int32_t close_reactor() = 0;virtual int32_t event_loop() = 0;virtual int32_t stop_event_loop() = 0;//事件操作//添加一个事件的监听virtual int32_t register_handler(CEventHandler *handler, uint32_t masks) = 0;//删除一个事件的特定监听virtual int32_t remove_handler(CEventHandler *handler, uint32_t masks) = 0;//删除一个事件virtual int32_t delete_handler(CEventHandler *handler, bool del_event_obj = false) = 0;//定时器操作 //添加一个定时器virtual uint32_t set_timer(CEventHandler *event_handler, const void *act, uint32_t delay) = 0;//删除一个定时器virtual uint32_t cancel_timer(uint32_t timer_id, const void **act) = 0;protected:IMessageProcessor* msg_proc_;};
其中 msg_proc_是内部消息队列处理器。

reactor的核心函数是event_loop,event_loop是事件轮询函数,所有的分时复用在其中实现,流程伪代码为:
void event_loop(){....//添加被监控的时间add_event_to_select(...);//设置SELECT堵塞时间struct timeval timeout;timeout.tv_sec = 0;timeout.tv_usec = select_delay_ * 1000;//进行SOCKET集合的事件扫描int32_t count = ::select(max_fd, &read_set, &write_set, &expeption_set, &timeout);if(count > 0) {//进行SOCKET的事件处理}//扫描定时器select_delay_ = timer_queue_.expire();//扫描内部消息队列if(msg_proc_ != NULL){msg_proc_->processor();}...}
event_loop最主要的工作就是扫描事件。

1.1 EventHandler

CEventHandler是处理reactor触发的事件的,当有事件到来,loop_event会找到对应的event handler进行触发,CEventHandler的事件分类枚举:
typedef enum EVENT_MASK{MASK_READ      = (1 << 0),//读事件MASK_WRITE     = (1 << 1),//写事件MASK_TIMEOUT   = (1 << 2),//超时事件MASK_EXCEPT    = (1 << 3),//异常事件}EVENT_MASK;
事件判断值采用2进制进位来表示,1个event_value是否是否是读事件
if(event_value & MASK_READ){             //进行读事件处理}
CEventHandler类接口一般只需要继承实现以下几个接口:
public:virtual int32_thandle_timeout(const void *act, uint32_t timer_id);//超时事件virtual int32_thandle_input(BASE_HANDLER handle);//socket读事件virtual int32_thandle_output(BASE_HANDLER handle);//socket写事件virtual int32_thandle_close(BASE_HANDLER handle, ReactorMask close_mask);//socket关闭virtual int32_thandle_exception(BASE_HANDLER handle);//socket异常
以上几个接口根据需要进行实现,例如:只需要实现一个定时器,只需要实现handle_timeout接口。

1.2 queue

revolver的消息队列实现其实很简单,通过一个继承IMessageProcessor并设置到reactor当中进行消息监听。IMessageProcessor是个即插即用的接口。revolver的消息队列定义如下:

template<class T, int32_t CAPACITY>class BaseQueue_T{public:BaseQueue_T(){data_ = new T[CAPACITY];rindex_ = 0;windex_ = 0;};~BaseQueue_T(){delete []data_;};bool put(const T& element){//像队列中PUT一个消息return true;};bool get(T& element){//从队列中get一下消息return true;};private:T*data_;volatile int32_trindex_;volatile int32_twindex_;
}
其中rindex_是队列读取位置,windex_是队列写入位置。T表示的是所用的消息类型。


1.3 Socket


以上SOCKET模块的继承和调用关系,BaseSocket是SOCKET的基础封装,主要是实现些send recv等函数,SocketDgram是UDP Socket的实现,SocketStream是TCP Socket的实现。SocketConnector是TCP连接器,CSocketAcceptor是TCP接收器。具体的可以看对应的代码。值得一提的是windows下的UDP Socket的ICMP处理问题,在UDP Socket在在open函数中有下面一段代码:
#ifdef WIN32 //解决WINSOCK2 的UDP端口ICMP的问题int32_t byte_retruned = 0;bool new_be = false;  int32_t status = WSAIoctl(handler_, SIO_UDP_CONNRESET,  &new_be, sizeof(new_be), NULL, 0, (LPDWORD)&byte_retruned, NULL, NULL);  #endif
这段代码是为了解决WINDOWS下reactor接收不到ICMP信号的问题。

1.4定时器

revolver的定时器是个相对较复杂的模块,以后打算用专门的篇幅来介绍。

备注:WINDOWS下的revolver只能用来做调试和测试作用,不可以用来做单独的服务。可以用来做客户端的网络模型。
0 0
原创粉丝点击