下图展示了Proactor框架提供的基本组件和通信过程的支持
直接介绍ACE_Proactor的框架请参考:http://www.blogbus.com/egeho123-logs/18118935.html
下面是本文要介绍的示例:
前摄式I/O ACE_Proactor框架和反应时I/O ACE_Reactor的主要区别就在于:前者异步读写(读写的发起和完成分开处理),后者同步读写。
这里主要讲个人对前者的理解:
(1)事件循环:ACE_Proactor模式使用ACE_Proactor::instance ()->proactor_run_event_loop();来监听事件
(2)ACE_Asynch_Connector<A_Service_Handler> connector;主动发起连接
(3)ACE_Asynch_Acceptor<B_Service_Handler> acceptor;被动监听等待连接的到来,并负责连接的建立;
(3.1)当来一个连接请求时,此类负责连接建立;连接建立之后会使用自己的make_handle方法创建一个链接处理对象:ACE_Service_Handler的派生类。调用ACE_Service_Handler派生类的open方法,从而读写操作就由ACE_Service_Handler的派生类来做。
(3.2)ACE_Service_Handler派生类怎么知道发送给谁呢?又怎么知道自己的地址呢?这是由于工厂类ACE_Asynch_Acceptor在创建ACE_Service_Handler派生类对象的时候会自动把本地地址和对端地址传递给ACE_Service_Handler派生类的对象。所以派生类对象在发送和接受的时候不需要知道地址信息
(3.3)由于ACE_Service_Handler派生类是从open开始执行,所以读写操作最开始都会放到这个open方法中来执行。
(4)异步读写的发起由ACE_Asynch_Write_Stream类和ACE_Asynch_Read_Stream来做,一般此类的对象作为ACE_Service_Handler类的派生类的成员。根据3.3可以知道,这个类在open调用的时候会获得ACE_Service_Handler派生类对象的地址信息,所以read和write方法都没有ACE_INET_Addr参数。
(5)ACE_Service_Handler的派生类拥有自动获取读写结果的能力,读写完成时会自动调用此类的方法:handle_read_stream,handle_write_stream,这个回调由ACE_Proactor来完成。
(6)ACE_Asynch_Read_Stream::Result这个类的对象主要在读完成时使用(handle_read_stream(const ACE_Asynch_Read_Stream::Result &result)),由于读发起的时候reader.read (*mb, mb->space ())指明了要读多长,所以这个result有个成员result.bytes_to_read()来与发起的时候对应,如果读的长度不够,还可以继续读剩下的:reader.read(*mb,result.bytes_to_read()-result.bytes_transferred()),当然这仅仅限于你读的内容固定长的时候。
具体实现用了两个项目Asynch_Connector和Asynch_Acceptor,一个用来连续发送,一个用来不停的接收
Asynch_Connector项目
客户端发送本地时间
time_client_main.cpp
#include <iostream> using namespace std; #include "ace/Message_Queue.h" #include "ace/Asynch_IO.h" #include "ace/OS.h" #include "ace/Proactor.h" #include "ace/Asynch_Connector.h" class Service_Handler : public ACE_Service_Handler { public: Service_Handler() { ACE_OS::printf("Service_Handler constructed for connector \n"); } ~Service_Handler () { if (this->handle () != ACE_INVALID_HANDLE) ACE_OS::closesocket (this->handle ()); ACE_OS::printf("one Service_Handler for connecter destructed"); } //把当前时间发送到远端 void send_to_accepter(void); virtual void open (ACE_HANDLE h, ACE_Message_Block&) { //在OPEN函数中完成读写操作 this->handle (h); //connect if (this->writer_.open (*this) != 0 ) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("Service_Handler open"))); delete this; return; } ACE_OS::printf("connceted\n"); send_to_accepter(); return; } //writer_.write()异步写完成后会调用此函数 virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result) { result.message_block ().release(); ACE_OS::sleep(1);//发送完成之后一定要暂停,给对方一个处理的时间。要不然一直发送对方接收不过来就会丢失。更为常见的情况不是暂停时间,而是接收对端发来的确认信息。就像本文一开始说的那样。 //上次发送完毕之后再接着发送一次,这次发送完成之后又会调用 //handle_write_stream,所以会一直发送 send_to_accepter(); return; } private: //用来向远端发送内容 ACE_Asynch_Write_Stream writer_; }; //把当前时间发送到远端 void Service_Handler::send_to_accepter(void) { time_t now = ACE_OS::gettimeofday().sec(); ACE_Message_Block *mb = new ACE_Message_Block(100); //获取当前时间的字符串格式 mb->copy( ctime(&now)); //send message to accepter if (this->writer_.write(*mb,mb->length()) !=0) { ACE_OS::printf("Begin write fail in open\n"); delete this; return; } else { ACE_OS::printf("sended %s\n",mb->rd_ptr()); } } int main(int argc, char *argv[]) { ACE_INET_Addr addr; addr.set(3000,ACE_LOCALHOST); char addr_buffer[50]={0}; addr.addr_to_string(addr_buffer,sizeof(addr_buffer)); cout<<"connecting["<<addr_buffer<<"]...."<<endl; ACE_Asynch_Connector<Service_Handler> connector; connector.open(); if (connector.connect(addr) == -1) return -1; ACE_Proactor::instance ()->proactor_run_event_loop(); return 0; }
Asynch_Acceptor项目
服务端接收对方时间
accepter_main.cpp
#include <iostream> using namespace std; #include "ace/Message_Queue.h" #include "ace/Asynch_IO.h" #include "ace/OS.h" #include "ace/Proactor.h" #include "ace/Asynch_Acceptor.h" class Service_Handler : public ACE_Service_Handler { public: Service_Handler() { ACE_OS::printf("Service_Handler constructed for accepter \n"); } ~Service_Handler () { if (this->handle () != ACE_INVALID_HANDLE) ACE_OS::closesocket (this->handle ()); ACE_OS::printf("one Service_Handler for accepter destructed"); } //异步读取消息 void reveive_from_connector(void); virtual void open (ACE_HANDLE h, ACE_Message_Block&) { this->handle (h); if (this->reader_.open (*this) != 0 ) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("Service_Handler open"))); delete this; return; } //异步读取 reveive_from_connector(); return; } //reader_.read()异步读完成后会调用此函数 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 () == 0) { mb.release (); delete this; return; } //输出读取内容 ACE_OS::printf("received:%s\n",mb.rd_ptr()); mb.release(); //继续下一次异步读取 reveive_from_connector(); } private: ACE_Asynch_Read_Stream reader_; char buffer[1024]; }; void Service_Handler::reveive_from_connector(void) { ACE_Message_Block *mb = new ACE_Message_Block(buffer,1024); if (this->reader_.read (*mb, mb->space ()) != 0) { ACE_OS::printf("Begin read fail\n"); delete this; return; } } int main(int argc, char *argv[]) { int port=3000; ACE_Asynch_Acceptor<Service_Handler> acceptor; if (acceptor.open (ACE_INET_Addr (port)) == -1) return -1; cout<<"listenning localhost["<<port<<"]...."<<endl; ACE_Proactor::instance ()->proactor_run_event_loop(); return 0; }
先运行接收程序,再运行发送程序,结果如下