ACE反应器模式:ACE_Reactor

    在服务器socket编程中,用来处理客户端的请求,最直接的做法是,为每一个socket连接创建一个线程,采用阻塞模式的方法来处理,然这种阻塞模式随着并发量增大,效果也会越来越差。一种比较好的方法就是select模型的思想。比如可把来自客户端的连接保存在一个cook中,采用轮询的方式检测某个连接是否可读或者可写。ACE反应器模式与这种思想类似。

    ACE_Reactor的使用很简单,在服务端可以注册两个事件,一个用来处理客户端的连接,这种是被动接受客户端的请求,这里称作ClientAcceptor,当接受到客户端请求时,注册一个事件用来专门负责和客户端通信,这里称作ClientService。这样在有N个连接的服务器就会出现一个ClientAcceptor对象和N个ClientService对象,当某一个客户端连接断开则删除cook中的记录,并析构掉一个ClientService对象。

以下是服务器一个实例:

头文件需要包括:

#include<ace/OS.h>
#include<ace/Reactor.h>
#include<ace/SOCK_Connector.h>
#include<ace/SOCK_Acceptor.h>
#include<ace/Auto_Ptr.h>ClientAcceptor:专门负责处理来自客户端的连接
class ClientAcceptor : public ACE_Event_Handler
{
public:
    virtual ~ClientAcceptor (){this->handle_close (ACE_INVALID_HANDLE, 0);}

    int open (const ACE_INET_Addr &listen_addr)
    {
        if (this->acceptor_.open (listen_addr, 1) == -1)
        {
            ACE_OS::printf("open port fail");
            return -1;
        }
        //注册接受连接回调事件
        returnthis->reactor ()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
    }

    virtual ACE_HANDLE get_handle (void) const
    { returnthis->acceptor_.get_handle (); }

    virtualint handle_input (ACE_HANDLE fd )
    {
        ClientService *client = new ClientService();
        auto_ptr<ClientService> p (client);

        if (this->acceptor_.accept (client->peer ()) == -1)
        {
            ACE_OS::printf("accept client fail");
            return -1;
        }
        p.release ();
        client->reactor (this->reactor ());
        if (client->open () == -1)
            client->handle_close (ACE_INVALID_HANDLE, 0);
        return 0;
    }
    
    virtualint handle_close (ACE_HANDLE handle,
        ACE_Reactor_Mask close_mask)
    {
        if (this->acceptor_.get_handle () != ACE_INVALID_HANDLE)
        {
            ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
                ACE_Event_Handler::DONT_CALL;
            this->reactor ()->remove_handler (this, m);
            this->acceptor_.close ();
        }
        return 0;
    }

protected:
    ACE_SOCK_Acceptor acceptor_;
};

ClientService:负责和客户端通信

class ClientService : public ACE_Event_Handler
{
public:
    ACE_SOCK_Stream &peer (void) { returnthis->sock_; }

    int open (void)
    {
        //注册读就绪回调函数
        returnthis->reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK);
    }

    virtual ACE_HANDLE get_handle (void) const { returnthis->sock_.get_handle (); }

    virtualint handle_input (ACE_HANDLE fd )
    {
        //一个简单的EchoServer,将客户端的信息返回
        int rev = peer().recv(buf,100);
        if(rev<=0)
            return -1;

        peer().send(buf,rev);
        return 0;
    }

    // 释放相应资源
virtualint handle_close (ACE_HANDLE, ACE_Reactor_Mask mask)
    {
        if (mask == ACE_Event_Handler::WRITE_MASK)
            return 0;
        mask = ACE_Event_Handler::ALL_EVENTS_MASK |
            ACE_Event_Handler::DONT_CALL;
        this->reactor ()->remove_handler (this, mask);
        this->sock_.close ();
        deletethis;    //socket出错时,将自动删除该客户端,释放相应资源
        return 0;
    }

protected:
    char buf[100];
    ACE_SOCK_Stream sock_;
};

main函数就更简单了:

int main(int argc, char *argv[]) 
{
    ACE_INET_Addr addr(3000,"192.168.1.142");
    ClientAcceptor server;
    server.reactor(ACE_Reactor::instance());
    server.open(addr);

    while(true)
    {
        ACE_Reactor::instance()->handle_events(); 
    }

    return 0; 
}实际上ACE反应器的功能还很强大,实现了多事件分离机制,将不同的事件类型交给不同的事件处理器,通过框架内部一张表来维护。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值