ACE_linux:Reactor与Proactor两种模式的区别

一、概念:

Reactor与Proactor两种模式的区别。这里我们只关注read操作,因为write操作也是差不多的。下面是Reactor的做法:

  1. 某个事件处理器宣称它对某个socket上的读事件很感兴趣;
  2. 事件分离者等着这个事件的发生;
  3. 当事件发生了,事件分离器被唤醒,这负责通知先前那个事件处理器;
  4. 事件处理器收到消息,于是去那个socket上读数据了. 如果需要,它再次宣称对这个socket上的读事件感兴趣,一直重复上面的步骤;

下面再来看看真正意义的异步模式Proactor是如何做的:

  1. 事件处理器直接投递发一个读操作(当然,操作系统必须支持这个异步操作)。这个时候,事件处理器根本不关心读事件,它只管发这么个请求,它魂牵梦萦的是这个读操作的完成事件。这个事件处理器很拽,发个命令就不管具体的事情了,只等着别人(系统)帮他搞定的时候给他回个话。
  2. 事件分离器等着这个读事件的完成(比较下与Reactor的不同);
  3. 当事件分离器默默等待完成事情到来的同时,操作系统已经在一边开始干活了,它从目标读取数据,放入用户提供的缓存区中,最后通知事件分离器,这个事情我搞完了;
  4. 事件分离器通知之前的事件处理器: 你吩咐的事情搞定了;
  5. 事件处理器这时会发现想要读的数据已经乖乖地放在他提供的缓存区中,想怎么处理都行了。如果有需要,事件处理器还像之前一样发起另外一个读操作,和上面的几个步骤一样。

二、代码示例:

-----------------------------------

Reactor:

-----------------------------------

-----------------------------------

Proactor:

  1 #include "ace/Proactor.h"
  2 #include "ace/Asynch_Acceptor.h"
  3
  4 class HA_Proactive_Service : public ACE_Service_Handler
  5 {
  6 public:
  7     HA_Proactive_Service()
  8     {
  9         ACE_OS::printf("Service_Handler constructed for accepter \n");
 10     }
 11     ~HA_Proactive_Service ()
 12     {
 13         if (this->handle () != ACE_INVALID_HANDLE)
 14         {
 15             ACE_OS::closesocket (this->handle ());
 16         }
 17     }
 18
 19     virtual void open (ACE_HANDLE h, ACE_Message_Block&)
 20     {
 21         //在OPEN函数中完成读写操作
 22         this->handle (h);
 23         if (this->reader_.open (*this) != 0 ||
 24                 this->writer_.open (*this) != 0   )
 25         {
 26             ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
 27                         ACE_TEXT ("HA_Proactive_Service open")));
 28
 29             return;
 30         }
 31         ACE_OS::printf("ready!\n");
 32
 33         //异步发送
 34         send_to_remote();
 35         //异步读取
 36         reveive_from_remote();
 37
 38         // mb is now controlled by Proactor framework.
 39         return;
 40     }
 41
 42     //异步读完成后会调用此函数
 43     virtual void handle_read_stream
 44     (const ACE_Asynch_Read_Stream::Result &result)
 45     {
 46         ACE_Message_Block &mb = result.message_block ();
 47         if (!result.success () || result.bytes_transferred () == 0)
 48         {
 49             mb.release ();
 50
 51             return;
 52         }
 53         //else
 54         //输出读取内容
 55         ACE_OS::printf("received:%s\n",mb.rd_ptr());
 56         mb.release();
 57         //继续下一次异步读取
 58         reveive_from_remote();
 59
 60         return;
 61     }
 62     //异步写完成后会调用此函数
 63     virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
 64     {
 65         result.message_block ().release();
 66         ACE_OS::sleep(1);
 67         //上次发送完毕之后再接着发送一次,这次发送完成之后又会调用
 68         //handle_write_stream,所以会一直发送
 69         send_to_remote();
 70         return;
 71     }
 72     //remote
 73     void reveive_from_remote(void)
 74     {
 75         ACE_Message_Block *mb;
 76         ACE_NEW_NORETURN (mb, ACE_Message_Block (1024));
 77         if (this->reader_.read (*mb, mb->space ()) != 0)
 78         {
 79             ACE_OS::printf("Begin read fail\n");
 80
 81             return;
 82         }
 83     }
 84     //把当前时间发送到远端
 85     void send_to_remote(void)
 86     {
 87         std::string book = "S: ";
 88         time_t now = ACE_OS::gettimeofday().sec();
 89         book = book+ ctime(&now);
 90         ACE_Message_Block *mb = new ACE_Message_Block(100);
 91         //获取当前时间的字符串格式
 92         mb->copy(book.c_str() );
 93         //send message to accepter
 94         if (this->writer_.write(*mb,mb->length()) !=0)
 95         {
 96             ACE_OS::printf("Begin write fail\n");
 97
 98             return;
 99         }
100         else
101         {
102             ACE_OS::printf("sended %s\n",mb->rd_ptr());
103         }
104     }
105
106     // Listing 3
107 private:
108     ACE_Asynch_Read_Stream reader_;
109     ACE_Asynch_Write_Stream writer_;
110 };
111
112
113 int main(int argc, char *argv[])
114 {
115     int port=3000;
116     ACE_Asynch_Acceptor<HA_Proactive_Service> acceptor;
117
118     if (acceptor.open (ACE_INET_Addr (port)) == -1)
119         return -1;
120
121     while(true)
122         ACE_Proactor::instance ()->handle_events ();
123
124     return 0;
125 }

Acceptor.cpp

  1 #include "ace/Proactor.h"
  2 #include "ace/Asynch_Connector.h"
  3
  4 class HA_Proactive_Service : public ACE_Service_Handler
  5 {
  6 public:
  7     HA_Proactive_Service()
  8     {
  9         ACE_OS::printf("Service_Handler constructed for connector \n");
 10     }
 11     ~HA_Proactive_Service ()
 12     {
 13         if (this->handle () != ACE_INVALID_HANDLE)
 14         {
 15             ACE_OS::closesocket (this->handle ());
 16         }
 17     }
 18
 19     virtual void open (ACE_HANDLE h, ACE_Message_Block&)
 20     {
 21         //在OPEN函数中完成读写操作
 22         this->handle (h);
 23
 24         if (this->reader_.open (*this) != 0 ||
 25                 this->writer_.open (*this) != 0   )
 26         {
 27             ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
 28                         ACE_TEXT ("HA_Proactive_Service open")));
 29
 30             return;
 31         }
 32
 33         ACE_OS::printf("connceted!\n");
 34         //异步发送
 35         send_to_remote();
 36         //异步读取
 37         reveive_from_remote();
 38
 39
 40         return;
 41     }
 42
 43     //异步读完成后会调用此函数
 44     virtual void handle_read_stream
 45     (const ACE_Asynch_Read_Stream::Result &result)
 46     {
 47         ACE_Message_Block &mb = result.message_block ();
 48         if (!result.success () || result.bytes_transferred () == 0)
 49         {
 50             mb.release ();
 51
 52             return;
 53         }
 54         //else
 55         //输出读取内容
 56         ACE_OS::printf("received:%s\n",mb.rd_ptr());
 57         mb.release();
 58         //继续下一次异步读取
 59         reveive_from_remote();
 60
 61         return;
 62     }
 63     //异步写完成后会调用此函数
 64     virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
 65     {
 66         result.message_block ().release();
 67         ACE_OS::sleep(1);
 68         //上次发送完毕之后再接着发送一次,这次发送完成之后又会调用
 69         //handle_write_stream,所以会一直发送
 70         send_to_remote();
 71         return;
 72     }
 73     //remote
 74     void reveive_from_remote(void)
 75     {
 76         ACE_Message_Block *mb;
 77         ACE_NEW_NORETURN (mb, ACE_Message_Block (1024));
 78         if (this->reader_.read (*mb, mb->space ()) != 0)
 79         {
 80             ACE_OS::printf("Begin read fail\n");
 81
 82             return;
 83         }
 84     }
 85     //把当前时间发送到远端
 86     void send_to_remote(void)
 87     {
 88         std::string book = "C: ";
 89         time_t now = ACE_OS::gettimeofday().sec();
 90         book = book+ ctime(&now);
 91         ACE_Message_Block *mb = new ACE_Message_Block(100);
 92         //获取当前时间的字符串格式
 93         mb->copy(book.c_str() );
 94         //send message to accepter
 95         if (this->writer_.write(*mb,mb->length()) !=0)
 96         {
 97             ACE_OS::printf("Begin write fail\n");
 98
 99             return;
100         }
101         else
102         {
103             ACE_OS::printf("sended %s\n",mb->rd_ptr());
104         }
105     }
106
107     // Listing 3
108 private:
109     ACE_Asynch_Read_Stream reader_;
110     ACE_Asynch_Write_Stream writer_;
111 };
112
113 int main(int argc, char *argv[])
114 {
115
116     ACE_INET_Addr addr(3000,"127.0.0.1");
117
118     ACE_Asynch_Connector<HA_Proactive_Service> connector;
119
120     connector.open();
121     if (connector.connect(addr) == -1)
122         return -1;
123
124     while(true)
125         ACE_Proactor::instance ()->handle_events ();
126
127     return 0;
128 }

Connector.cpp

-----------------------------------

GOOD LUCK!

时间: 2024-10-05 11:40:05

ACE_linux:Reactor与Proactor两种模式的区别的相关文章

【转】Reactor与Proactor两种模式区别

转自:http://www.cnblogs.com/cbscan/articles/2107494.html 两种IO多路复用方案:Reactor and Proactor 一般情况下,I/O 复用机制需要事件分享器(event demultiplexor [1, 3]). 事件分享器的作用,即将那些读写事件源分发给各读写事件的处理者,就像送快递的在楼下喊: 谁的什么东西送了, 快来拿吧.开发人员在开始的时候需要在分享器那里注册感兴趣的事件,并提供相应的处理者(event handlers),或

vue-router 的两种模式的区别

Vue Router 是Vue官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌.vue-router 默认 hash 模式,还有一种是history模式. hash模式 hash模式的工作原理是hashchange事件,可以在window监听hash的变化.我们在url后面随便添加一个#xx触发这个事件. window.onhashchange = function(event){ console.log(event); } 打印出来的结果如下: 可以看到里边有

Unity下Iso和Persp两种模式的区别

Iso模式 平行视野.在Iso模式下,不论物体距离摄像头远近都给人的感觉是一样大的. Persp模式 透视视野.在persp模式下,物体在scene界面上所呈现的画面是给人一种距离摄像头近的物体显示的大,距离摄像头远的物体显示的小. 原文地址:https://www.cnblogs.com/OctoptusLian/p/8848216.html

Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程

Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程 这里的函数式编程的设计以muduo为例进行对比说明: Reactor实现架构对比 面向对象的设计类图如下: 函数式编程以muduo为例,设计类图如下: 面向对象的Reactor方案设计 我们先看看面向对象的设计方案,想想为什么这么做: 拿出Reactor事件驱动的模式设计图,对比来看,清晰明了: 从左边开始,事件驱动,需要一个事件循环和IO分发器,EventLoop和Poller很好理解:为了让事件驱动支持多平台,Poller上加

Doctype文档声明的严格模式和混杂模式,如何触发这两种模式,区分它们有何意义?

(1)如何触发两种模式:加入xml头部声明,可以触发IE浏览器的Quirks mode,触发之后,浏览器解析方式就和IE5.5一样,拥有IE5.5一样的bug和其他问题,行为(Javascript)也是如此.          (2)IE6的触发:在XHTML的DOCTYPE前加入XML声明,<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD X

第九章 两种模式的比较

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include

DUI-分层窗口两种模式(SetLayeredWindowAttributes和UpdateLayeredWindow两种方法各有利弊)

LayeredWindow提供两种模式: 1.使用SetLayeredWindowAttributes去设置透明度, 完成窗口的统一透明,此时窗口仍然收到PAINT消息, 其他应用跟普通窗口一样. 2.使用UpdateLayeredWindow方法, 向系统提交包含bitmap的DC, 交由系统统一管理,此时再也收不到paint消息, 任何对窗口的改变,只能通过UpdateLayeredWindow来修改. 如果你不需要针对像素级别的不同透明,只需要使用SetLayeredWindowAttri

如何理解DocType? 什么是严格模式与混杂模式?如何触发这两种模式?

1.Doctype声明位于文档中的最前面的位置,处于标签之前,此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范,该标签可声明三种DTD 类型,分别表示严格版本.过渡版本以及基于框架的 HTML 文档.2.当浏览器厂商开始创建与标准兼容的浏览器时,为了确保向后兼容性,他们把浏览器的工作模式(渲染模式)分为标准模式和混杂模式.在标准模式中,浏览器根据规范呈现页面:在混杂模式中,页面以一种比较宽松的向后兼容的方式显示,混杂模式通常模拟老式浏览器的行为以防止老站点无法工作.3.如何触发这两

Doctype 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?

Doctype:(Document Type)文档类型,它位于文档中最前面的位置,处于标签之前.如果你想制作符合标准的页面,一个必不可少的关键组成部分就是DOCTYPE的声明.确定了正确的Doctype,xhtml里面的标识和css才能正常生效(也就是说它会很负责地告诉浏览器怎么解释你的这个标签和你写的css).既然它是一种声明,它的责任就是告诉浏览器文档使用哪种html或者xhtml规范.为了获取正确的Doctype声明,关键就是让dtd与文档所遵循的标准对应.例如:假定文档遵循的是xhtml