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

转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/595938.html

在服务器端使用Reactor框架

使用Reactor框架的服务器端结构如下:

服务器端注册两种事件处理器,ClientAcceptor和ClientService ,ClientService类负责和客户端的通信,每一个ClientService对象对应一个客户端的Socket连接。 ClientAcceptor专门负责被动接受客户端的连接,并创建ClientService对象。这样,在一个N个Socket连接的服务器程序中,将存在1个ClientAcceptor对象和N个ClientService对象。

整个服务器端流程如下:

  1. 首先创建一个ClientAcceptor对象,该对象在Reactor上注册ACCEPT_MASK事件,Reactor将自动在监听端口建立Socket监听。
  2. 如果有对该端口的Socket连接时,Reactor将自动回调handle_input方法,ClientAcceptor重载此方法,并创建一个ClientService对象,用于处理和Client的通信。
  3. ClientService对象根据服务器的具体功能实现,其处理过程和客户端程序类似,注册相应的回调事件并分发即可。

代码如下:

  1 #include <ace/OS.h>
  2 #include <ace/Reactor.h>
  3 #include <ace/SOCK_Connector.h>
  4 #include <ace/SOCK_Acceptor.h>
  5 #include <ace/Auto_Ptr.h>
  6
  7 class ClientService : public ACE_Event_Handler
  8 {
  9 public:
 10     ACE_SOCK_Stream &peer (void) { return this->sock_; }
 11
 12     int open (void)
 13     {
 14         //注册读就绪回调函数
 15         return this->reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK);
 16     }
 17
 18     virtual ACE_HANDLE get_handle (void) const { return this->sock_.get_handle (); }
 19
 20     virtual int handle_input (ACE_HANDLE fd )
 21     {
 22         //一个简单的EchoServer,将客户端的信息返回
 23         int rev = peer().recv(buf,100);
 24         if(rev<=0)
 25             return -1;
 26
 27         peer().send(buf,rev);
 28         return 0;
 29     }
 30
 31     // 释放相应资源
 32 virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask mask)
 33     {
 34         if (mask == ACE_Event_Handler::WRITE_MASK)
 35             return 0;
 36         mask = ACE_Event_Handler::ALL_EVENTS_MASK |
 37             ACE_Event_Handler::DONT_CALL;
 38         this->reactor ()->remove_handler (this, mask);
 39         this->sock_.close ();
 40         delete this;    //socket出错时,将自动删除该客户端,释放相应资源
 41         return 0;
 42     }
 43
 44 protected:
 45     char buf[100];
 46     ACE_SOCK_Stream sock_;
 47 };
 48
 49 class ClientAcceptor : public ACE_Event_Handler
 50 {
 51 public:
 52     virtual ~ClientAcceptor (){this->handle_close (ACE_INVALID_HANDLE, 0);}
 53
 54     int open (const ACE_INET_Addr &listen_addr)
 55     {
 56         if (this->acceptor_.open (listen_addr, 1) == -1)
 57         {
 58             ACE_OS::printf("open port fail");
 59             return -1;
 60         }
 61         //注册接受连接回调事件
 62         return this->reactor ()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
 63     }
 64
 65     virtual ACE_HANDLE get_handle (void) const
 66     { return this->acceptor_.get_handle (); }
 67
 68     virtual int handle_input (ACE_HANDLE fd )
 69     {
 70         ClientService *client = new ClientService();
 71         auto_ptr<ClientService> p (client);
 72
 73         if (this->acceptor_.accept (client->peer ()) == -1)
 74         {
 75             ACE_OS::printf("accept client fail");
 76             return -1;
 77         }
 78         p.release ();
 79         client->reactor (this->reactor ());
 80         if (client->open () == -1)
 81             client->handle_close (ACE_INVALID_HANDLE, 0);
 82         return 0;
 83     }
 84
 85     virtual int handle_close (ACE_HANDLE handle,
 86         ACE_Reactor_Mask close_mask)
 87     {
 88         if (this->acceptor_.get_handle () != ACE_INVALID_HANDLE)
 89         {
 90             ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
 91                 ACE_Event_Handler::DONT_CALL;
 92             this->reactor ()->remove_handler (this, m);
 93             this->acceptor_.close ();
 94         }
 95         return 0;
 96     }
 97
 98 protected:
 99     ACE_SOCK_Acceptor acceptor_;
100 };
101
102 int main(int argc, char *argv[])
103 {
104     ACE_INET_Addr addr(3000,"192.168.1.142");
105     ClientAcceptor server;
106     server.reactor(ACE_Reactor::instance());
107     server.open(addr);
108
109     while(true)
110     {
111         ACE_Reactor::instance()->handle_events();
112     }
113
114     return 0;
115 }

代码功能比较简单,需要注意以下几点:

  1. 这里注册事件的方式和前面的文章中方式不一样,是通过ACE_Event_Handler类的reactor()方法设置和获取reactor的指针,比较直观和方便。前面的文章是通过ACE_Reactor::instance()来获取的一个单体reactor的指针。
  2. 当客户端Socket连接关闭时,需要释放相应资源,需要注意一下ClientService对象的handle_close方法中释放资源的相应代码。
时间: 2024-10-06 13:23:20

ACE反应器(Reactor)模式(3)的相关文章

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

转载于:http://www.cnblogs.com/TianFang/archive/2006/12/13/591332.html 1.ACE反应器框架简介 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞.所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待状态, 直到有东西可读或者可写为止.而对于非阻塞状态, 如果没有东西可读, 或者不可写

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

转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/595808.html 在Socket编程中,常见的事件就是"读就绪","写就绪",通过对这两个事件的捕获分发,可以实现Socket中的异步操作. Socket编程中的事件处理器 在前面我们已经介绍过,在ACE反应器框架中,任何都必须派生自ACE_Event_Handler类,并通过重载其相应会调事件处理函数来实现相应的回调处理的.在Socket编程中,我们

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

转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/596012.html 定时器的实现 通过Reactor机制,还可以很容易的实现定时器的功能,使用方式如下. 编写一个事件反应器,重载handle_timeout()方法,该方法是定时器的触发时间到时,会自动触发该方法. 通过Reactor的schedule_timer()方法注册定时器. 启动reacotr的handle_events()事件分发循环. 当不想使用定时器时,可以通过Re

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

原文出自http://www.cnblogs.com/binchen-china,禁止转载. 在之前的文章中提到过Reactor模式和Preactor模式,现在利用ACE的Reactor来实现一个基于Reactor框架的服务器. 首先回顾下Reactor模式和Preactor模式. Reactor模式: Reactor模式实现非常简单,使用同步IO模型,即业务线程处理数据需要主动等待或询问,主要特点是利用epoll监听listen描述符是否有响应,及时将客户连接信息放于一个队列,epoll和队列

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

Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或者叫召唤兽. 并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量. 先用比较直观的方式来介绍一下这种方式的优点,通过和常用的多线程方式比较一下,可能更好理解. 以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐.就像一个网站会有很多的请

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

Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或者叫召唤兽. 并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量. 先用比较直观的方式来介绍一下这种方式的优点,通过和常用的多线程方式比较一下,可能更好理解. 以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐.就像一个网站会有很多的请

Reactor模式,或者叫反应器模式[转]

这个写的相当易懂, 再次感谢并分享,原地址: http://daimojingdeyu.iteye.com/blog/828696 Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或者叫召唤兽. 并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量. 先用比较直观的方式来介绍一下这种方式的优点,通过和常用的

Reactor模式(反应器模式)

Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或者叫召唤兽. 并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量. 先用比较直观的方式来介绍一下这种方式的优点,通过和常用的多线程方式比较一下,可能更好理解. 以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐.就像一个网站会有很多的请

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

Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或者叫召唤兽. 并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量. 先用比较直观的方式来介绍一下这种方式的优点,通过和常用的多线程方式比较一下,可能更好理解. 以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐.就像一个网站会有很多的请