ACE反应器模式:ACE_Reactor

来源:互联网 发布:php 文件上传代码 编辑:程序博客网 时间:2024/04/28 09:39

    在服务器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