转载于:http://www.cnblogs.com/TianFang/archive/2006/12/31/608952.html

当 OS 平台支持异步操作时,一种高效而方便的实现高性能 Web 服务器的方法是使用前摄式事件分派。使用前摄式事件分派模型设计的 Web 服务器通过一或多个线程控制来处理异步操作的完成。这样,通过集成完成事件多路分离(completion event demultiplexing)和事件处理器分派,前摄器模式简化了异步的 Web 服务器。

异步的 Web 服务器将这样来利用前摄器模式:首先让 Web 服务器向 OS 发出异步操作,并将回调方法登记到 Completion Dispatcher(完成分派器),后者将在操作完成时通知 Web 服务器。于是 OS 代表 Web 服务器执行操作,并随即在一个周知的地方将结果排队。Completion Dispatcher 负责使完成通知出队,并执行适当的、含有应用特有的 Web 服务器代码的回调。

使用前摄器模式的主要优点是可以启动多个并发操作,并可并行运行,而不要求应用必须拥有多个线程。操作被应用异步地启动,它们在 OS 的 I/O 子系统中运行直到完成。发起操作的线程现在可以服务 另外的请求了。

在ACE中,可以通过ACE_Proactor实现前摄器模式。实现方式如下。

1。创建服务处理器:

Proactor框架中服务处理器均派生自ACE_Service_Handler,它和Reactor框架的事件处理器非常类似。当发生IO操作完成事件时,会触发相应的事件完成会调函数。

2。实现服务处理器IO操作

Proactor框架中所有的IO操作都由相应的异步操作类来完成,这些异步操作类都继承自ACE_Asynch_Operation。常用的有以下几种。

  1. ACE_Asynch_Read_Stream, 提供从TCP/IP socket连接中进行异步读操作.
  2. ACE_Asynch_Write_Stream, 提供从TCP/IP socket连接中进行异步写操作.

使用这些操作类的一般方式如下:

  1. 初始化
    将相关的操作注册到服务处理器中,一般可通过调用其open方法实现。
  2. 发出IO操作
    发出异步IO操作请求,该操作不会阻塞,具体的IO操作过程由操作系统异步完成。
  3. IO操作完成回调处理
    异步IO操作完成后,OS会触发服务处理器中的相应回调函数,可通过该函数的ACE_Asynch_Result参数获取相应的返回值。

3。使用连接器或接受器和远端进行连接

ACE为Proactor框架提供了两个工厂类来建立TCP/IP连接。

  1. ACE_Asynch_Acceptor, 用于被动地建立连接
  2. ACE_Asynch_Connector 用于主动地建立连接

当远端连接建立时,连接器或接受器便会创建相应的服务处理器,从而可以实现服务处理。

4。启动Proactor事件分发处理

启动事件分发处理只需如下调用:

while(true)
        ACE_Proactor::instance ()->handle_events ();

5。程序示例

服务器端:

服务器端简单的实现了一个EchoServer,流程如下:

当客户端建立连接时,首先发出一个异步读的异步请求,当读完成时,将所读的数据打印出来,并发出一个新的异步请求。

 #include "ace/Message_Queue.h"
#include "ace/Asynch_IO.h"
#include "ace/OS.h"
#include "ace/Proactor.h"
#include "ace/Asynch_Acceptor.h" class HA_Proactive_Service : public ACE_Service_Handler
{
public:
~HA_Proactive_Service ()
{
if (this->handle () != ACE_INVALID_HANDLE)
ACE_OS::closesocket (this->handle ());
} virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
this->handle (h);
if (this->reader_.open (*this) != )
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("HA_Proactive_Service open")));
delete this;
return;
} ACE_Message_Block *mb = new ACE_Message_Block(buffer,);
if (this->reader_.read (*mb, mb->space ()) != )
{
ACE_OS::printf("Begin read fail\n");
delete this;
return;
} return;
} //异步读完成后会调用此函数
virtual void handle_read_stream
(const ACE_Asynch_Read_Stream::Result &result)
{
ACE_Message_Block &mb = result.message_block ();
if (!result.success () || result.bytes_transferred () == )
{
mb.release ();
delete this;
return;
} mb.copy(""); //为字符串添加结束标记'\0'
ACE_OS::printf("rev:\t%s\n",mb.rd_ptr());
mb.release(); ACE_Message_Block *nmb = new ACE_Message_Block(buffer,);
if (this->reader_.read (*nmb, nmb->space ()) != ) return;
} private:
ACE_Asynch_Read_Stream reader_;
char buffer[];
}; int main(int argc, char *argv[])
{
int port=;
ACE_Asynch_Acceptor<HA_Proactive_Service> acceptor; if (acceptor.open (ACE_INET_Addr (port)) == -)
return -; while(true)
ACE_Proactor::instance ()->handle_events (); return ;
}

客户端:

客户端代码比较简单,就是每隔1秒钟将当前的系统时间转换为字符串形式通过异步形式发送给服务器,发送完成后,释放时间字符的内存空间。

 #include "ace/Message_Queue.h"
#include "ace/Asynch_IO.h"
#include "ace/OS.h"
#include "ace/Proactor.h"
#include "ace/Asynch_Connector.h" class HA_Proactive_Service : public ACE_Service_Handler
{
public:
~HA_Proactive_Service ()
{
if (this->handle () != ACE_INVALID_HANDLE)
ACE_OS::closesocket (this->handle ());
} virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
this->handle (h);
if (this->writer_.open (*this) != )
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("HA_Proactive_Service open")));
delete this;
return;
} ACE_OS::printf("connceted"); for(int i=;i<;i++) //每隔秒中发送时间至服务器
{
ACE_OS::sleep();
time_t now = ACE_OS::gettimeofday().sec();
char *time = ctime(&now); //获取当前时间的字符串格式
ACE_Message_Block *mb = new ACE_Message_Block();
mb->copy(time); if (this->writer_.write(*mb,mb->length()) !=)
{
ACE_OS::printf("Begin read fail\n");
delete this;
return;
}
} return;
} //异步写完成后会调用此函数
virtual void handle_write_dgram
(const ACE_Asynch_Write_Stream::Result &result)
{
ACE_Message_Block &mb = result.message_block ();
mb.release();
return;
} private:
ACE_Asynch_Write_Stream writer_;
}; int main(int argc, char *argv[])
{ ACE_INET_Addr addr(,"192.168.1.142"); HA_Proactive_Service *client = new HA_Proactive_Service();
ACE_Asynch_Connector<HA_Proactive_Service> connector; connector.open();
if (connector.connect(addr) == -)
return -; while(true)
ACE_Proactor::instance ()->handle_events (); return ;
}

ACE前摄器Proactor模式的更多相关文章

  1. 设计模式-前摄器模式(Proactor)

    本周要进行boost asio库的学习,在学习之前发现最好需要先了解一下前摄器模式,这样对asio库的理解很有帮助,故写下此文 我之前写的随笔XShell的模拟实现中的链接方式可以说是同步的(服务器阻 ...

  2. 【转】第8章 前摄器(Proactor):用于为异步事件多路分离和分派处理器的对象行为模式

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  3. 对于观察者模式,Reactor模式,Proactor模式的一点理解

    最近就服务器程序IO效率这一块了解一下设计模式中的Reacotr模式和proactor模式,感觉跟观察者模式有些类似的地方,网上也看了一些其他人对三者之间区别的理解,都讲得很仔细,在此根据自己的理解做 ...

  4. (原创)拨开迷雾见月明-剖析asio中的proactor模式(二)

    在上一篇博文中我们提到异步请求是从上层开始,一层一层转发到最下面的服务层的对象win_iocp_socket_service,由它将请求转发到操作系统(调用windows api),操作系统处理完异步 ...

  5. 两种高效的事件处理模型:Reactor模式和Proactor模式

    随着IO多路复用技术的出现,出现了很多事件处理模式.同步I/O模型通常由Reactor模式实现,而异步I/O模型则由Proactor模式实现. Reactor模式: Reator类图如上所示,Reac ...

  6. Reactor模式与Proactor模式

    该文章总结了网上资源对这两种模式的描述 原文地址:http://www.cnblogs.com/dawen/archive/2011/05/18/2050358.html 1.标准定义 两种I/O多路 ...

  7. 高性能IO设计的Reactor和Proactor模式(转)

    在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作. 在比较这两个模式之前,我们首先的搞明白 ...

  8. (原创)拨开迷雾见月明-剖析asio中的proactor模式(一)

    使用asio之前要先对它的设计思想有所了解,了解设计思想将有助于我们理解和应用asio.asio是基于proactor模式的,asio的proactor模式隐藏于大量的细节当中,要找到它的踪迹,往往有 ...

  9. 同步异步阻塞非阻塞Reactor模式和Proactor模式 (目前JAVA的NIO就属于同步非阻塞IO)

    在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作. 在比较这两个模式之前,我们首先的搞明白 ...

随机推荐

  1. C++11 type_traits 之is_same源码分析

    请看源码: template<typename _Tp, _Tp __v> struct integral_constant { static const _Tp value = __v; ...

  2. 丑哭了CSDN。

    真是不知道如何设置,忒,,,,不知如何表达.

  3. 树的层次遍历(Trees on the level,UVA 122)

    题目描述: 题目思路: 1.用结构链表来建树 2.用队列来实现层次遍历,当遍历到根节点时,将其子节点压入队列 #include <iostream> #include <cstdli ...

  4. adb 常用命令及操作

    获取序列号: adb get-serialno 查看连接计算机的设备: adb devices 重启机器: adb reboot 重启到bootloader,即刷机模式: adb reboot boo ...

  5. Docker 镜像构建的时候,应该小心的坑

    不要改文件 如果run了以后,你还需要进入到容器中,修改容器的配置,那么,这个容器是危险的.一旦容器无法启动,就再也改不了配置.那么你就需要删除和重新run这个容器,而配置要再改一遍.一个可用的镜像在 ...

  6. usdt信息小结

    https://blog.csdn.net/weixin_42208011/article/details/80499536 https://blog.csdn.net/weixin_42208011 ...

  7. 有道云笔记Markdown使用

    目录 使用规则 代码高亮 制作待办事项 高效绘图 基本规则 使用规则 代码高亮 #include <iostream> #include <string> using name ...

  8. Python中如何Getting Help

    在Python中Gettting Help有如下两种方法: 1 使用dir函数,dir的参数可以是一个真正的对象实例,也可以是一个数据类型,无论哪种情形,dir函数都返回与这个对象或者数据类型相关联的 ...

  9. 软件工程第四周作业之四则运算-C#实现

    拿到题目的时候,快放假了,也没心思做.十月七号的一下午大概从两点做到八点半,加上十月八号的十二点半到两点半,做了一共八个半小时,去掉吃饭半个小时那么一共做了八个小时. 逆波兰表达式我是扒的别人代码,没 ...

  10. 软件工程-东北师大站-第二次作业psp

    1.本周PSP 2.本周进度条 3.本周累计进度图 代码累计折线图 博文字数累计折线图 本周PSP饼状图