转载于:http://www.cnblogs.com/TianFang/archive/2006/12/13/591332.html

1.ACE反应器框架简介

反应器(Reactor):用于事件多路分离和分派的体系结构模式

通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。

在前面的章节中提到的Tcp通信的例子中,就是采用的阻塞式的工作方式:当接收tcp数据时,如果远端没有数据可以读,则会一直阻塞到读到需要的数据为止。这种方式的传输和传统的被动方法的调用类似,非常直观,并且简单有效,但是同样也存在一个效率问题,如果你是开发一个面对着数千个连接的服务器程序,对每一个客户端都采用阻塞的方式通信,如果存在某个非常耗时的读写操作时,其它的客户端通信将无法响应,效率非常低下。

一种常用做法是:每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。

另一种较高效的做法是:服务器端保存一个Socket连接列表,然后对这个列表进行轮询,如果发现某个Socket端口上有数据可读时(读就绪),则调用该socket连接的相应读操作;如果发现某个Socket端口上有数据可写时(写就绪),则调用该socket连接的相应写操作;如果某个端口的Socket连接已经中断,则调用相应的析构方法关闭该端口。这样能充分利用服务器资源,效率得到了很大提高。

在Socket编程中就可以通过select等相关API实现这一方式。但直接用这些API控制起来比较麻烦,并且也难以控制和移植,在ACE中可以通过Reactor模式简化这一开发过程。

反应器本质上提供一组更高级的编程抽象,简化了事件驱动的分布式应用的设计和实现。除此而外,反应器还将若干不同种类的事件的多路分离集成到易于使用的API中。特别地,反应器对基于定时器的事件、信号事件、基于I/O端口监控的事件和用户定义的通知进行统一地处理。

ACE中的反应器与若干内部和外部组件协同工作。其基本概念是反应器框架检测事件的发生(通过在OS事件多路分离接口上进行侦听),并发出对预登记事件处理器(event handler)对象中的方法的"回调"(callback)。该方法由应用开发者实现,其中含有应用处理此事件的特定代码。

使用ACE的反应器,只需如下几步:

  1. 创建事件处理器,以处理他所感兴趣的某事件。
  2. 在反应器上登记,通知说他有兴趣处理某事件,同时传递他想要用以处理此事件的事件处理器的指针给反应器。

随后反应器框架将自动地:

  1. 在内部维护一些表,将不同的事件类型与事件处理器对象关联起来。
  2. 在用户已登记的某个事件发生时,反应器发出对处理器中相应方法的回调。

反应器模式在ACE中被实现为ACE_Reactor类,它提供反应器框架的功能接口。

如上面所提到的,反应器将事件处理器对象作为服务提供者使用。反应器内部记录某个事件处理器的特定事件的相关回调方法。当这些事件发生时,反应器会创建这种事件和相应的事件处理器的关联。

  1. 事件处理器
    事件处理器就是需要通过轮询发生事件改变的对象列表中的对象,如在上面的例子中就是连接的客户端,每个客户端都可以看成一个事件处理器。
  2. 回调事件
    就是反应器支持的事件,如Socket读就绪,写就绪。拿上面的例子来说,如果某个客户端(事件处理器)在反应器中注册了读就绪事件,当客户端给服务器发送一条消息的时候,就会触发这个客户端的数据可读的回调函数。

在反应器框架中,所有应用特有的事件处理器都必须由ACE_Event_Handler的抽象接口类派生。可以通过重载相应的"handle_"方法实现相关的回调方法。

使用ACE_Reactor基本上有三个步骤:

  1. 创建ACE_Event_Handler的子类,并在其中实现适当的"handle_"方法,以处理你想要此事件处理器为之服务的事件类型。
  2. 通过调用反应器对象的register_handler(),将你的事件处理器登记到反应器。
  3. 在事件发生时,反应器将自动回调相应的事件处理器对象的适当的handle_"方法。

下面我就以一个Socket客户端的例子为例简单的说明反应器的基本用法。

 #include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/SOCK_Connector.h> #include <string>
#include <iostream>
using namespace std; class MyClient:public ACE_Event_Handler
{
public:
bool open()
{
ACE_SOCK_Connector connector;
ACE_INET_Addr addr(,"127.0.0.1");
ACE_Time_Value timeout(,);
if(connector.connect(peer,addr,&timeout) != )
{
cout<<endl<<"connecetd fail";
return false;
}
ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK);
cout<<endl<<"connecetd ";
return true;
} ACE_HANDLE get_handle(void) const
{
return peer.get_handle();
} int handle_input (ACE_HANDLE fd)
{
int rev=;
ACE_Time_Value timeout(,);
if((rev=peer.recv(buffer,,&timeout))>)
{
buffer[rev]='\0';
cout<<endl<<"rev:\t"<<buffer<<endl;
}
return ;
} private:
ACE_SOCK_Stream peer;
char buffer[];
}; int main(int argc, char *argv[])
{
MyClient client;
client.open(); while(true)
{
ACE_Reactor::instance()->handle_events();
} return ;
}

在这个例子中,客户端连接上服务器后,通过ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK)注册了一个读就绪的回调函数,当服务器端给客户端发消息的时候,会自动触发handle_input()函数,将接收到的信息打印出来。

这个例子只是为了演示反应器的基本用法,并不完善,我将在下一节中对如何在Socket通信中使用反应器做进一步的介绍。

ACE反应器(Reactor)模式(1)的更多相关文章

  1. ACE反应器(Reactor)模式(2)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/595808.html 在Socket编程中,常见的事件就是"读就绪" ...

  2. ACE反应器(Reactor)模式(4)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/596012.html 定时器的实现 通过Reactor机制,还可以很容易的实现定时器的功 ...

  3. ACE反应器(Reactor)模式(3)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/595938.html 在服务器端使用Reactor框架 使用Reactor框架的服务器端 ...

  4. 反应器(Reactor)模式

    Java NIO非堵塞技术实际是采取反应器模式,或者说是观察者(observer)模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必开启多个线程死等,从外界看,实现了流畅的I/ ...

  5. ACE - Reactor模式源码剖析及具体实现(大量源码慎入)

    原文出自http://www.cnblogs.com/binchen-china,禁止转载. 在之前的文章中提到过Reactor模式和Preactor模式,现在利用ACE的Reactor来实现一个基于 ...

  6. 什么是Reactor模式,或者叫反应器模式

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

  7. Reactor模式,或者叫反应器模式

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

  8. Reactor模式(反应器模式)

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

  9. Reactor模式,或者叫反应器模式 - 为什么用多路io复用提供吞吐量

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

随机推荐

  1. lintcode50 数组剔除元素后的乘积

    数组剔除元素后的乘积 给定一个整数数组A. 定义B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], 计算B的时候请不要使用除法. 您在真实的面试中是 ...

  2. lr 常用操作

    lr脚本编写语法: web_add_cookie();:服务器注入cookies lr_save_string("网址或其他","参数2");:一个保存函数,它 ...

  3. 校招小白机考入坑之从键盘输入java的各种数据类型

    //1.从键盘输入一个整型(其他基本类型类似) Scanner sc =new Scanner(System.in); sc.hasNextInt(); int str1 = sc.nextInt() ...

  4. Java学习笔记-13.创建窗口和程序片

    1.init()方法:程序片第一次被创建,初次运行初始化程序片时调用. start()方法:每当程序片进入web浏览器中,并且允许程序片启动他的常规操作时调用(特殊的程序片被stop()关闭):同样在 ...

  5. 十:HDFS Short-Circuit Local Reads 短路本地读取

    当client请求数据时,datanode会读取数据然后通过TCP协议发送给client.short-circuit绕过了datanode直接读取数据.short-circuit的前提是client和 ...

  6. URAL 1297 Palindrome(Manacher)

    The “U.S. Robots” HQ has just received a rather alarming anonymous letter. It states that the agent ...

  7. python正则表达式函数match()和search()的区别详解

    match()和search()都是python中的正则匹配函数,那这两个函数有何区别呢? match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找 ...

  8. java—连连看-实现消除

    实现消除 1.Chess.java package Linkup; /** * 棋子封装类 * * @author laixl * */ public class Chess { // 图片的 状态 ...

  9. <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<二>

    <Item 9> Never call virtual functions during construction or destruction 1.you shouldn't call ...

  10. #Leetcode# 951. Flip Equivalent Binary Trees

    https://leetcode.com/problems/flip-equivalent-binary-trees/ For a binary tree T, we can define a fli ...