找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 8509|回复: 1

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

[复制链接]
发表于 2012-2-29 00:26:48 | 显示全部楼层 |阅读模式
现有的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()方法设置所有者线程。

发表于 2012-8-20 23:23:13 | 显示全部楼层
关于ACE_Proactor的下次再聊。我好像找不到这篇了???
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-21 20:38 , Processed in 0.014605 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表