ACE网络开发中,各种Reactor实现的总结

大家好,第一次来这个属于ACEer的地方真的很高兴啊!下面就ACE中现有的三种Reactor做一些总结,都是我个人使用的经验,如有不妥还请指教。

最近,偶在ACE_Reactor框架和ACE_Proactor框架的基础上写了一个网络应用框架,主要目的是将网络数据收发,网络错误处理,以及网络超时这些socket级的问题与应用逻辑分开,可以保证在应用逻辑的实现不变的情况下,随意改变网络层的实现(也就是用同步IO的ACE_Reactor框架或者用ACE_Proactor框架实现socket上的数据收发,超时及错误处理)。写这个网络应用框架的过程中遇到了很多问题,不得不去看ACE_Reactor框架和ACE_Proactor框架的源代码,所以最后对这两个框架有了更深的认识。下面说说ACE_Reactor框架,都是我个人使用的经验,如有不妥还请指教。

现有的ACE库中提供了三种主要的Reactor实现(更多新的实现到官方网站上应该可以找到),ACE_Select_Reactor, ACE_TP_Reactor和ACE_WFMO_Reactor。三种实现的使用都有不同的注意事项:

(1)ACE_WFMO_Reactor:这个实现是基于Win32的Socket Event-select模型,也就是用一个win32 的手动重置event与一个socket相关联(调用WSAEventSelect函数并指明关心哪些socket事件,如可读,可写等),用WaitForMutiple0bjects来实现多路IO监视,当这个函数返回后调用WSAEnumNetworkEvents检查socket上发生了那种事件(可读或可写)。   这个实现问题最大。 首先,它的致命伤在于每一个ACE_WFMO_Reactor只能同时监视64个socket(具体说是62个,有2个用于notify()和参与event-loop线程的唤醒同步);其次,就是它的可写条件非常诡异,只有当socket内部写缓冲区从满到不满时才算可写,因此,向它register_event 写事件时不出意外的话一定出错(第一次写成功,以后就再写不了了)。因此,这个实现用途很有限。不过,这个实现可以保证多个线程同时对同一个reactor执行event_loop,为了达到这个目的,它在多线程同步上下了很多工夫,读它的源代码会是很好的学习机会(牛人写的就是不一样啊,win32 event的使用简直是登峰造极)。

(2)ACE_Select_Reactor:这个实现中归中举,不要忘记在线程执行event_loop前成为这个reactor的owner。值得学习的是实现中使用的那把锁的实现, 即ACE_Token类,以后自己写程序的时候可以用得上,比mutex强很多。另外就是notify()的实现,也就是那个ACE_Pipe类,说白了就是本地回环socket来实现线程间通信。这个实现和(1)可以在其他线程(也就是没有执行Reactor_Event_Loop的线程)中安全的调用Remove_Handler,这个很方便,一般就可以在handle_close()方法里面做清理handler的工作。但是有一个问题注意,要自己跟踪每个handler注册了那些事件,只有向reactor注销了这些时间后才能delete这个handler。这个问题在C++ NPv2中强调过。这个实现默认是可以同时监视1024个socket,不过可惜的是只能一个线程执行Reactor_Event_Loop。

(3)ACE_TP_Reactor:这个是我最喜欢的了,但是如果不清楚它的实现的话会很容易出错。如果你使用了多个线程run_reactor_event_loop:首先,在默认情况下,你不能象前两个实现那样在不需要某个handler的情况下安全的调用remove_handler();其次,你需要在handle_input(),和handle_timeout()以及handle_output(),和handle_timeout()中考虑同步,注意是handle_**put与handle_timeout()之间才有同步问题,而handle_input()和handle_output()之间不用考虑。解决第一个问题的办法是在ACE_Event_handler中启动reference_count,并且改变删除策略:在handle_close()中不进行任何清除工作,而是将ACE_Event_handler的reference_count减一,而清除工作应该在析构函数中进行。那么,delete是谁调用呢---是reactor框架ACE_Event_handler在reference_count为0时帮你调用。总之,这个实现的使用要比其他的复杂。

总之,Reactor的使用远比那几本书上讲的要复杂得多,如果不彻底了解它是怎么实现的,在使用过程中难免会碰到许多问题。所以,我的建议是,看源代码!这样不仅可以深入理解Reactor框架,少犯错误,还可以学习大牛们怎么写程序的,特别是对于设计模式,还有操作系统API的灵活使用。关于ACE_Proactor的下次再聊。



提一些自己的看法,大家讨论。

1、ACE_WFMO_Reactor部分,向它register_event 写事件时不出意外的话一定出错,应用中没发现,因为这个实现中, 事件在当前状态变化时候触发,而不是基于当前状态触发。所以,注册了写标志后,你就一直发送就行了,直到它告诉你不成了,再等待handle_output()被触发。
2、ACE_Select_Reactor部分,不过可惜的是只能一个线程执行Reactor_Event_Loop,这个不准确。准确的说,是在某一时刻只能被一个线程执行。可以使用多个线程,但是每个线程循环中必须使用owner()方法设置所有者线程。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACE Reactor是一个用于事件驱动的框架,主要用于处理异步事件。它的接口声明放在Reactor.h,接口的实现分别放在Reactor.cpp和Reactor.ini文件,而Reactor.inl作为内联函数直接在Reactor.h文件包含了。其内部实现主要封装在ACE_Reactor_Impl类 。 在ACE_Select_Reactor_Notify类,有一个指向ACE_Select_Reactor的指针select_reactor_。如果该指针为空,那么Reactor管理器将不支持Notify事件 。 ACE_Reactor的run_reactor_event_loop方法用于处理事件的循环。它会调用handle_events方法,该方法是由ACE_Reactor_Impl对象指针的成员函数实现的。handle_events的作用是在超时时间到或事件触发时才返回,并返回ACE_Event_Handlers派发的总数。与altertable_handle_events不同的是,在eventloop,当系统将一个I/O完成例程或一个异步过程调用排队时才会返回。eventloop指的是run_reactor_event_loop方法的while(1)的循环 。 综上所述,ACE Reactor是一个用于处理事件驱动的框架,它通过封装不同的实现来提供事件处理和调度的功能,并支持异步事件处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ACE_Reactor(一)整体理解ACE_Reactor](https://blog.csdn.net/chinaclock/article/details/49021839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值