zoukankan      html  css  js  c++  java
  • 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方法中释放资源的相应代码。
  • 相关阅读:
    PHP 获取请求里的 header字段以及发送header
    宝塔链接数据库
    链表中头结点和头指针
    git How to resolve a Git “CONFLICT (modify/delete)”?
    yii 执行mysql:既要添加数据又要更新数据
    recv() failed (104: Connection reset by peer) while reading response header from upstream
    Linux磁盘空间满了,定位到mysql日志,删除
    mysql 字符乱码
    php message queue
    CGI 、fastcgi、php-cgi、php-fpm
  • 原文地址:https://www.cnblogs.com/shmilxu/p/4860528.html
Copyright © 2011-2022 走看看