WFMO_Reactor的与众不同

 

5              WFMO_Reactor的与众不同

WFMO_ReactorACE_ReactorWindows下的默认实现(为什么不选择ACE_Select_Reactor作为默认实现,可能是基于效率和强大性的考虑),WFMO_Reactor的低层使用的函数是WaitForMultipleObjectsWSAEventSelectWSAEnumNetworkEvents。其中WaitForMultipleObjects函数用于处理线程,互斥量,信号灯,事件,定时器等事件,而WSAEventSelect用于处理网络IO事件。

由于Windows API和操作系统的特性不一样,WFMO_Reactor在很多地方的表现和其他平台不一致。 【注】

 

【注】其实这两个问题在《C++ Network Programming Volume 2 - Systematic Reuse with ACE and Frameworks》中4.4 The ACE_WFMO_Reactor Class有说明。这儿算是借花献佛。

 

5.1               WFMO_Reactor只能处理62个句柄

由于WaitForMultipleObjects不是一个处理大量事件的函数,其最多处理64个事件句柄,而WFMO_Reactor自身为了处理使用了2个句柄,所以一个WFMO_Rector对象只能处理。

如果你想做大规模的网络接入,62个事件句柄显然是不够的,特别是要同时处理IO事件时,导致这个不足的应该是WFMO_Reactor的设计者的一个选择。在赋予WFMO_Reactor强大的特性的同时,WFMO_Reactor的设计者只能让网络IO事件的数量委屈一下了。

5.2               WRITE_MASK触发机制

WFMO_Reactor 选择的是WindowsWSAEventSelect 函数作为网络的IO的反应器。但是WSAEventSelect函数的FD_WRITE的事件处理和传统的IO反应器(select)不同。下面是MSDN的描述。

The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with connect/WSAConnect or accepted with accept/WSAAccept, and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure, the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set.

简单翻译就是,只有在三种条件下,WSAEventSelect才会发出FD_WRITE通知,一是使用connectWSAConnect,一个套接字成功建立连接后;二是使用acceptWSAAccept,套接字被接受以后;三是若sendWSASendsendtoWSASendTo函数返回失败,而且错误是WSAEWOULDBLOCK错误后,缓冲区的空间再次变得可用时。【注】

 

【注】这种触发方式在IO反应器或者说IO多路复用模型中应该被称为边缘触发方式。select函数好像没有这种触发方式而是水平触发方式, Epoll是支持这种方式的,但是默认还是水平触发,这种方式可能有更高的效率,但是代码更加难写。

 

可以这么理解,WSAEventSelect认为套接字基本都是可写状态,它认为你应该大胆send。只有send出现WSAEWOULDBLOCK失败后,你才需要使用WSAEventSelect反应器。【注】

所以对于WFMO_Reactor的,你不可能依靠注册(或者是唤醒)IO句柄进行写操作,WMFO_Reactor很有可能不会去回调你的handle_output函数。

 

【注】对于网络套接字,只要缓冲区还有空间就可以直接发送,除非缓冲区没有空间了,才可能出现阻塞错误,所以直接send失败的可能性很小,另外反复调用注册IO句柄一类的操作其实是比较耗时的。其实先send,如果send失败再注册IO句柄到反应器的方式应该是一种更加高效的方式,高压力的通讯服务器应该选择这个编写方式。

我自己的通信服务器通过这个改造,提高的性能在15%左右(CPU占用率下降)。

 

由于WFMO_Reactor的这些特点,其实很大的限制了Reactor的可移植性。其实个人感觉如果你对系统特性没有那么多要求,在Windows下选择Select_Reactor替换WFMO_Reactor是更好的选择。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值