ACE_linux:Reactor与Proactor两种模式的区别
一、概念:
Reactor与Proactor两种模式的区别。这里我们只关注read操作,因为write操作也是差不多的。下面是Reactor的做法:
某个事件处理器宣称它对某个socket上的读事件很感兴趣;
事件分离者等着这个事件的发生;
当事件发生了,事件分离器被唤醒,这负责通知先前那个事件处理器;
事件处理器收到消息,于是去那个socket上读数据了. 如果需要,它再次宣称对这个socket上的读事件感兴趣,一直重复上面的步骤;
下面再来看看真正意义的异步模式Proactor是如何做的:
事件处理器直接投递发一个读操作(当然,操作系统必须支持这个异步操作)。这个时候,事件处理器根本不关心读事件,它只管发这么个请求,它魂牵梦萦的是这个读操作的完成事件。这个事件处理器很拽,发个命令就不管具体的事情了,只等着别人(系统)帮他搞定的时候给他回个话。
事件分离器等着这个读事件的完成(比较下与Reactor的不同);
当事件分离器默默等待完成事情到来的同时,操作系统已经在一边开始干活了,它从目标读取数据,放入用户提供的缓存区中,最后通知事件分离器,这个事情我搞完了;
事件分离器通知之前的事件处理器: 你吩咐的事情搞定了;
事件处理器这时会发现想要读的数据已经乖乖地放在他提供的缓存区中,想怎么处理都行了。如果有需要,事件处理器还像之前一样发起另外一个读操作,和上面的几个步骤一样。
二、代码示例:
ACE_Proactor::run_event_loop(); 循环启动
ACE_Proactor::end_event_loop(); 循环停止
-----------------------------------
Reactor:
-----------------------------------
-----------------------------------
Proactor:
#include "ace/Proactor.h"
#include "ace/Asynch_Acceptor.h" class HA_Proactive_Service : public ACE_Service_Handler
{
public:
HA_Proactive_Service()
{
ACE_OS::printf("Service_Handler constructed for accepter \n");
}
~HA_Proactive_Service ()
{
if (this->handle () != ACE_INVALID_HANDLE)
{
ACE_OS::closesocket (this->handle ());
}
} virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
//在OPEN函数中完成读写操作
this->handle (h);
if (this->reader_.open (*this) != ||
this->writer_.open (*this) != )
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("HA_Proactive_Service open"))); return;
}
ACE_OS::printf("ready!\n"); //异步发送
send_to_remote();
//异步读取
reveive_from_remote(); // mb is now controlled by Proactor framework.
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 (); return;
}
//else
//输出读取内容
ACE_OS::printf("received:%s\n",mb.rd_ptr());
mb.release();
//继续下一次异步读取
reveive_from_remote(); return;
}
//异步写完成后会调用此函数
virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
{
result.message_block ().release();
ACE_OS::sleep();
//上次发送完毕之后再接着发送一次,这次发送完成之后又会调用
//handle_write_stream,所以会一直发送
send_to_remote();
return;
}
//remote
void reveive_from_remote(void)
{
ACE_Message_Block *mb;
ACE_NEW_NORETURN (mb, ACE_Message_Block ());
if (this->reader_.read (*mb, mb->space ()) != )
{
ACE_OS::printf("Begin read fail\n"); return;
}
}
//把当前时间发送到远端
void send_to_remote(void)
{
std::string book = "S: ";
time_t now = ACE_OS::gettimeofday().sec();
book = book+ ctime(&now);
ACE_Message_Block *mb = new ACE_Message_Block();
//获取当前时间的字符串格式
mb->copy(book.c_str() );
//send message to accepter
if (this->writer_.write(*mb,mb->length()) !=)
{
ACE_OS::printf("Begin write fail\n"); return;
}
else
{
ACE_OS::printf("sended %s\n",mb->rd_ptr());
}
} // Listing 3
private:
ACE_Asynch_Read_Stream reader_;
ACE_Asynch_Write_Stream writer_;
}; 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 ;
}
Acceptor.cpp
#include "ace/Proactor.h"
#include "ace/Asynch_Connector.h" class HA_Proactive_Service : public ACE_Service_Handler
{
public:
HA_Proactive_Service()
{
ACE_OS::printf("Service_Handler constructed for connector \n");
}
~HA_Proactive_Service ()
{
if (this->handle () != ACE_INVALID_HANDLE)
{
ACE_OS::closesocket (this->handle ());
}
} virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
//在OPEN函数中完成读写操作
this->handle (h); if (this->reader_.open (*this) != ||
this->writer_.open (*this) != )
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("HA_Proactive_Service open"))); return;
} ACE_OS::printf("connceted!\n");
//异步发送
send_to_remote();
//异步读取
reveive_from_remote(); 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 (); return;
}
//else
//输出读取内容
ACE_OS::printf("received:%s\n",mb.rd_ptr());
mb.release();
//继续下一次异步读取
reveive_from_remote(); return;
}
//异步写完成后会调用此函数
virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
{
result.message_block ().release();
ACE_OS::sleep();
//上次发送完毕之后再接着发送一次,这次发送完成之后又会调用
//handle_write_stream,所以会一直发送
send_to_remote();
return;
}
//remote
void reveive_from_remote(void)
{
ACE_Message_Block *mb;
ACE_NEW_NORETURN (mb, ACE_Message_Block ());
if (this->reader_.read (*mb, mb->space ()) != )
{
ACE_OS::printf("Begin read fail\n"); return;
}
}
//把当前时间发送到远端
void send_to_remote(void)
{
std::string book = "C: ";
time_t now = ACE_OS::gettimeofday().sec();
book = book+ ctime(&now);
ACE_Message_Block *mb = new ACE_Message_Block();
//获取当前时间的字符串格式
mb->copy(book.c_str() );
//send message to accepter
if (this->writer_.write(*mb,mb->length()) !=)
{
ACE_OS::printf("Begin write fail\n"); return;
}
else
{
ACE_OS::printf("sended %s\n",mb->rd_ptr());
}
} // Listing 3
private:
ACE_Asynch_Read_Stream reader_;
ACE_Asynch_Write_Stream writer_;
}; int main(int argc, char *argv[])
{ ACE_INET_Addr addr(,"127.0.0.1"); ACE_Asynch_Connector<HA_Proactive_Service> connector; connector.open();
if (connector.connect(addr) == -)
return -; while(true)
ACE_Proactor::instance ()->handle_events (); return ;
}
Connector.cpp
ACE_Proactor::run_event_loop(); <==>
while(true)
ACE_Proactor::instance ()->handle_events ();
//增加线程池
#include "ace/Proactor.h"
#include "ace/Asynch_Acceptor.h"
#include "ace/Task_T.h"
#include "ace/Thread_Semaphore.h" class Receive : public ACE_Service_Handler
{
public:
Receive()
{
ACE_OS::printf("Service_Handler constructed for accepter \n");
}
~Receive ()
{
if (this->handle () != ACE_INVALID_HANDLE)
{
ACE_OS::closesocket (this->handle ());
}
} virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
//在OPEN函数中完成读写操作
this->handle (h);
if (this->reader_.open (*this) != ||
this->writer_.open (*this) != )
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("Receive open"))); return;
}
ACE_OS::printf("ready!\n"); //异步发送
//send_to_remote();
//异步读取
reveive_from_remote(); // mb is now controlled by Proactor framework.
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 (); return;
} //输出读取内容
//ACE_OS::printf("received:%s\n",mb.rd_ptr());
ACE_DEBUG((LM_DEBUG,"(%t)received:%s\n",mb.rd_ptr()));
mb.release(); //继续下一次异步读取
reveive_from_remote(); return;
}
//异步写完成后会调用此函数
virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
{
result.message_block ().release();
ACE_OS::sleep();
//上次发送完毕之后再接着发送一次,这次发送完成之后又会调用
//handle_write_stream,所以会一直发送
send_to_remote();
return;
}
//remote
void reveive_from_remote(void)
{
ACE_Message_Block *mb;
ACE_NEW_NORETURN (mb, ACE_Message_Block ());
if (this->reader_.read (*mb, mb->space ()) != )
{
ACE_OS::printf("Begin read fail\n"); return;
}
}
//把当前时间发送到远端
void send_to_remote(void)
{
std::string book = "S: ";
time_t now = ACE_OS::gettimeofday().sec();
book = book+ ctime(&now);
ACE_Message_Block *mb = new ACE_Message_Block();
//获取当前时间的字符串格式
mb->copy(book.c_str() );
//send message to accepter
if (this->writer_.write(*mb,mb->length()) !=)
{
ACE_OS::printf("Begin write fail\n"); return;
}
else
{
ACE_OS::printf("sended %s\n",mb->rd_ptr());
}
} // Listing 3
private:
ACE_Asynch_Read_Stream reader_;
ACE_Asynch_Write_Stream writer_;
}; class Accepte : public ACE_Asynch_Acceptor<Receive>
{
public:
virtual Receive* make_handler(void)
{
return new Receive();
} }; class Proactor_Task : public ACE_Task<ACE_MT_SYNCH>
{
public: int star(int nMax)
{
create_proactor();
this->activate (THR_NEW_LWP, nMax);
for (;nMax>;nMax--)
{
sem_.acquire();
}
return ;
}
int stop()
{
ACE_Proactor::end_event_loop();
this->wait();
return ;
} virtual int svc (void)
{
ACE_DEBUG((LM_INFO,ACE_TEXT("svc method is invoked!\n")));
sem_.release(); ACE_Proactor::run_event_loop(); return ;
} int create_proactor()
{
ACE_Proactor::instance (); return ;
} int release_proactor()
{
ACE_Proactor::close_singleton ();
return ;
} ACE_Thread_Semaphore sem_;
}; int ACE_TMAIN(int ,char*[])
{
Proactor_Task task;
task.star(); Accepte accepte;
accepte.open(ACE_INET_Addr (), , ,ACE_DEFAULT_BACKLOG,,ACE_Proactor::instance()); //主函数退出控制
{
int nExit=;
while (nExit==)
scanf("%d",&nExit);
} return ;
} /*
int main(int argc, char *argv[])
{
int port=3000;
ACE_Asynch_Acceptor<Receive> acceptor; if (acceptor.open (ACE_INET_Addr (port)) == -1)
return -1; ACE_Proactor::run_event_loop(); return 0;
}
*/
Proactor_Task.cpp
-----------------------------------
GOOD LUCK!
ACE_linux:Reactor与Proactor两种模式的区别的更多相关文章
- 【转】Reactor与Proactor两种模式区别
转自:http://www.cnblogs.com/cbscan/articles/2107494.html 两种IO多路复用方案:Reactor and Proactor 一般情况下,I/O 复用机 ...
- vue-router的两种模式的区别
众所周知,vue-router有两种模式,hash模式和history模式,这里来谈谈两者的区别. ### hash模式 hash模式背后的原理是`onhashchange`事件,可以在`window ...
- 在IDEA中将项目部署到Tomcat的方法及两种模式的区别
转自:https://www.jianshu.com/p/fb0ed26c35d5 1.添加tomcat服务器 点右上角编辑配置 编辑配置 点击左上角+选择tomcat服务器 添加tomcat ...
- MODBUS ASCII和RTU两种模式的区别、优缺点
转自:http://blog.sina.com.cn/s/blog_89f286ad0102uzju.html 下表是MODBUS ASCII协议和RTU协议的比较: 协议 开始标记 结束标记 校验 ...
- vue-router 的两种模式的区别
Vue Router 是Vue官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌.vue-router 默认 hash 模式,还有一种是history模式. hash模 ...
- vue-router两种模式的区别
参考文献:https://blog.csdn.net/lla520/article/details/77894985/ https://segmentfault.com/a/1190000015123 ...
- Unity下Iso和Persp两种模式的区别
Iso模式 平行视野.在Iso模式下,不论物体距离摄像头远近都给人的感觉是一样大的. Persp模式 透视视野.在persp模式下,物体在scene界面上所呈现的画面是给人一种距离摄像头近的物体显示的 ...
- Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程
Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程 这里的函数式编程的设计以muduo为例进行对比说明: Reactor实现架构对比 面向对象的设计类图如下: 函数式编程以muduo为例 ...
- Windows2003 IIS6.0支持32位和64位两种模式的设置方法
IIS 6.0 可支持 32 位和 64 位两种模式.但是,IIS 6.0 不支持在 64 位版本的 Windows 上同时运行这两种模式.ASP.NET 1.1 只在 32 位模式下运行.而 ASP ...
随机推荐
- Android & Eclipse FAQ
一.eclipse中格式化代码快捷键Ctrl+Shift+F失效的解决办法 当我要格式化代码的时候,右键-source-format能够起效,但ctrl+shift+f不好使了. google之后来发 ...
- 解决iphone横屏时字体变大问题或者内容大小不一样等
在样式表中增加: @media screen and (max-device-width: 320px){body{-webkit-text-size-adjust:none}} @media scr ...
- Logback日志使用详解
概述 Logback建立于三个主要类之上:日志记录器(Logger),输出端(Appender)和日志格式化器(Layout).这三种组件协同工作,使开发者可以按照消息类型和级别来记录消息,还可以在程 ...
- 如何用eclispe远程调试tomcat--转载
原文地址:http://jingyan.baidu.com/article/0320e2c1f4ef6b1b87507b06.html tomcat是一种非常常见的java web应用服务器,有时候服 ...
- [改善Java代码]用整数类型处理货币
建议22:用整数类型处理货币. public class Client { public static void main(String[] args) { System.out.println(&q ...
- 关于Eclipse(MyEclipse)中一次性批量导入多个项目Project.
以前更换Eclipse(MyEclipse)的时候要想把原Eclipse中的项目导入到新的Eclipse中的做法是: 1.先把原Eclipse中工作空间中的项目(不包括.metadata文件夹)复制到 ...
- Jersey(1.19.1) - Deploying a RESTful Web Service
JAX-RS provides a deployment agnostic abstract class Application for declaring root resource and pro ...
- Linux 命令 - ping: 向网络主机发送 ICMP ECHO_REQUEST 包
ping 命令会向指定的网络主机发送特殊网络数据报 IMCP ECHO_REQUEST.多数网络设备收到该数据包后会做出回应,通过此法即可验证网络连接是否正常. 有时从安全角度出发,通常会配置部分网络 ...
- Android Wi-Fi基本操作
从用户角度看,Android Wi-Fi模块自下向上可以看为5层:硬件驱动程序,wpa_suppplicant,JNI,WiFi API,WifiSettings应用程序. 1.wpa_supplic ...
- Android 中的图像特效(Matrix)
以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,现在在Android中有一个Matrix类,它的中文意思就是矩阵.Matrix主要是用于图像的缩放.平移.旋转.扭曲等操作.图像处理,主要用到的 ...