ACE_Proactor TCP(接收什么就打印什么)V1.3

下图展示了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; 
}


先运行接收程序,再运行发送程序,结果如下



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值