下图展示了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;
}
先运行接收程序,再运行发送程序,结果如下