简单的ACE反应器(Reactor)模式服务器

在服务器端使用Reactor框架

使用Reactor框架的服务器端结构如下:

服务器端注册两种事件处理器,Cli_acceptor和Cli_server ,Cli_server类负责和客户端的通信,每一个Cli_server对象对应一个客户端的Socket连接。 Cli_acceptor专门负责被动接受客户端的连接,并创建Cli_server对象。这样,在一个N个Socket连接的服务器程序中,将存在1个Cli_acceptor对象和N个Cli_server对象。

整个服务器端流程如下:

首先创建一个Cli_acceptor对象,该对象在Reactor上注册ACCEPT_MASK事件,Reactor将自动在监听端口建立Socket监听。
如果有对该端口的Socket连接时,Reactor将自动回调handle_input方法,Cli_acceptor重载此方法,并创建一个Cli_server对象,用于处理和Client的通信。
Cli_server对象根据服务器的具体功能实现,其处理过程和客户端程序类似,注册相应的回调事件并分发即可。

下面为Cli_server.h:`

#ifndef GGGGG
#define GGGGG
#include"ace/Event_Handler.h"
#include"ace/Log_Msg.h"
#include"ace/SOCK_Stream.h"
#include"ace/Reactor.h"
class Cli_server : public ACE_Event_Handler
{
    public:
        Cli_server();
        ~Cli_server();
        const ACE_SOCK_Stream &get_Stream();
        void set_ptr(Cli_server*);
        void set_Stream(const ACE_SOCK_Stream peer);
        int register_read();
        virtual int handle_input(ACE_HANDLE fd);
        virtual ACE_HANDLE get_handle() const;
        virtual int handle_close(ACE_HANDLE ,ACE_Reactor_Mask close_mask);
    private:
        ACE_SOCK_Stream peer;
        Cli_server *cliser;
        bool nd_dt;
};
#endif`

先解释三个成员变量, peer负责真正的通信,cliser和nd_dt是为了释放资源(可能我用的是虚拟机,ACE中的智能指针貌似用不了,只能手动释放资源),若果nd_dt为true,就需要释放。这个到用的时候会详细解释。

构造函数和析构函数就不说了。
get_Stream():函数可以省略不管,没什么用。

set_Stream():用来设置peer的值,这个函数用一个ACE_SOCK_Stream对象作为参数,注意这个 按值传递,具体原因后面会解释。

register_read():用来注册读事件,将peer的读事件注册到反应器。

handle_input():十分重要的函数,当我们注册的事件发生时,会调用这个函数。这个函数从父类
ACE_Event_Handler继承而来,你必须重写它。

handle_close():在其他handle_*()挂钩方法中的一个返回-1时,或是在ACE_Reactor::remove_handler()被显式调用来解除事件处理器的登记时,执行用户定义的终止活动的挂钩方法

get_handle():这个函数同handle_input()继承自父类,你必须重载它,这个函数后面的const修饰词必须加上(C++多态,方法后是否有const也是一种重载),这个函数会在注册的时候用上,这个函数返回实际的I/O handle,我们这个类即返回peer的handle

下面为Cli_server.cpp:

#include"Cli_server.h"
const ACE_SOCK_Stream& Cli_server::get_Stream() //可以忽略
{
    ACE_DEBUG((LM_DEBUG,ACE_TEXT("get_Stream() : \n")));
    return peer;
}

void Cli_server::set_Stream(const ACE_SOCK_Stream  peer)
{
    ACE_DEBUG((LM_DEBUG,ACE_TEXT("set_Stream() : \n")));
    this->peer=peer;       //peer赋值,按值传递
}

int Cli_server::register_read()
{
    ACE_DEBUG((LM_DEBUG,ACE_TEXT("register_read() : \n")));
    return ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK);
    //注册读事件,在这个函数执行中,会调用this->get_handle()这个语句,将实际的handle与事件   相关联,若get_handle()函数返回错误的handle或者后面没有const修饰词,就会造成注册失败
}

ACE_HANDLE Cli_server::get_handle() const
{
    return peer.get_handle();//返回peer的handle,即实际做事情的handle
}

int Cli_server::handle_input(ACE_HANDLE fd)
{
    char recvbuf[100]={};  //测试用代码,这个可以随意写
    if(peer.recv(recvbuf,sizeof(recvbuf))<0)
    {
        ACE_DEBUG((LM_ERROR,ACE_TEXT("recv error ! \n")));
        return -1;
    }
    char sendbuf[20]="hello world!";
    peer.send_n(sendbuf,sizeof(sendbuf));
    return 0;
}
int Cli_server::handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask)
{
    close_mask=ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL;
    this->reactor()->remove_handler(this,close_mask);
    peer.close();
    return 0;
}

Cli_server::Cli_server():cliser(NULL),nd_dt(false)
{

}

void Cli_server::set_ptr(Cli_server * ptr)
{
    nd_dt=true;   //这个函数是为了释放内存
    cliser=ptr;
}
Cli_server::~Cli_server()
{
    if(nd_dt)
      delete cliser;  //释放内存
}

下面为Cli_acceptor.h:

#ifndef HHHHHHHHHHHHHH
#define HHHHHHHHHHHHHH
#include"ace/Log_Msg.h"
#include"ace/Event_Handler.h"
#include"ace/SOCK_Acceptor.h"
#include"ace/INET_Addr.h"
#include"Cli_server.h"
#include<memory>
class Cli_acceptor : public ACE_Event_Handler
{
    public:
        ~Cli_acceptor();
        const ACE_SOCK_Acceptor& get_Acceptor();
        void set_Acceptor(const ACE_SOCK_Acceptor& );
        virtual ACE_HANDLE get_handle() const;
        int open(const ACE_INET_Addr &);
        virtual int handle_input(ACE_HANDLE);
        virtual int handle_close(ACE_HANDLE,ACE_Reactor_Mask);
    private:
        ACE_SOCK_Acceptor acceptor;
};
#endif

成员变量为一个ACE_SOCK_Acceptor对象,来完成实际的监听工作和接收连接。
handle_input(),handle_close(),get_handle()就不说了。
get_Acceptor()可以忽略
open():这个函数执行bind(),listen()操作,其实就是实际执行acceptor.open()函数

下面为Cli_acceptor.cpp:

#include"Cli_acceptor.h"
const ACE_SOCK_Acceptor& Cli_acceptor::get_Acceptor()
{
    return acceptor;
}

void Cli_acceptor::set_Acceptor(const ACE_SOCK_Acceptor&acceptor)
{
    this->acceptor=acceptor;
}

int Cli_acceptor::open(const ACE_INET_Addr &addr)
{
    if(acceptor.open(addr,1)==-1) //执行acceptor.open()函数
    {
        ACE_DEBUG((LM_ERROR,ACE_TEXT("Cli_acceptor :: open error!\n")));
        return -1;
    }
    return ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::ACCEPT_MASK);
    //注册事件
}


int Cli_acceptor::handle_input(ACE_HANDLE fd)
{
    ACE_SOCK_Stream peer;  //这里就是为什么传值而不是传引用,若为引用的话这里就必须为一个指针或者静态变量,但都不符合要求。(智能指针我电脑不能用,静态变量,呵呵)所以这里我用的是传值,当然这里最后用指针动态分配,你们可以自己试一下
    if(acceptor.accept(peer)!=0)
    {
        ACE_DEBUG((LM_ERROR,ACE_TEXT("ACE_acceptor :: handle_input error!\n")));
        return -1;
    }
    Cli_server *cliser=new Cli_server;   //这个。一个连接对应一个Cli_server对象,这个必须要动态生成了,但是没有地方释放资源,所以就有了set_ptr()这个函数和那两个成员变量,就是为了释放这里的资源
    cliser->set_ptr(cliser);
    cliser->set_Stream(peer);//设置peer
    cliser->register_read();//注册读事件
    return 0;
}

int Cli_acceptor::handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask)
{
    close_mask=ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL;
    this->reactor()->remove_handler(this,close_mask);
    acceptor.close();
}

Cli_acceptor::~Cli_acceptor()
{
    this->handle_close(ACE_INVALID_HANDLE,0);
}

ACE_HANDLE Cli_acceptor::get_handle() const
{
    return acceptor.get_handle();
}

好了两个类已经介绍完了,下面就是main()函数中的内容,当你完成两个类后,就会发现,main()函数很好写,下面为ser.cpp:

#include"ace/Log_Msg.h"
#include"ace/SOCK_Acceptor.h"
#include"ace/SOCK_Stream.h"
#include"ace/INET_Addr.h"
#include"ace/Reactor.h"
#include"ace/SOCK_Connector.h"
#include"Cli_acceptor.h"
int ACE_TMAIN(int argc,ACE_TCHAR**argv)
{
    Cli_acceptor acceptor;          //一个接受连接的对象
    ACE_INET_Addr addr(6666);       //IP地址
    acceptor.open(addr);            //完成bind()和listen()
    while(1)
      ACE_Reactor::instance()->handle_events();//激发事件轮询
    return 1;
}

ACE的事件注册,我大概有一个猜想,但是我不敢肯定,我会查找一些资料再说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值