一个基于ACE的C/S服务程序实例

使用ACE进行C/S结构程序就是使用Reactor框架,实现我们的事件处理方法。下面是一个使用ACE开发的通信系统的简单的类图:

其中我们需要开发的部分主要就是Server_svc_handler和Client_svc_handler,这两个对象都是继承自ACE_svc_handler。用来处理建立(接受)连接,以及进行数据的通信和处理。
Server_acceptor是用于在服务器上接受连接,它与Server_svc_handler绑定,每当有新的连接时,ACE的Reactor框架就会创建一个Server_svc_handler的对象,然后把新连接的socket(ACE_SOCK_STREAM)绑定到这个handler上,以后就用这个handler处理这个socket上接收到的数据。
Client_connector与Acceptor类似,用于在客户端连接服务器,连接成功后,也由Reactor框架创建一个Client_svc_handler对象,并将它与连接后的socket绑定,来处理从服务器端接收到的数据。
下面就是几个类的代码。

class Server_svc_handler : public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>  
{  
public:  
    Server_svc_handler()  
    {  
        data= new char[DATA_SIZE];  
    }  
    int open(void*)  
    {  
        ACE_DEBUG((LM_DEBUG, "%P|%t, %s", " Connection established.\n")); //打印debug级别的log,%P%t表示进程号和线程号,%s是要打印的消息。  
        ACE_Reactor::instance()->register_handler(this,  ACE_Event_Handler::READ_MASK); //注册socket上可读事件的处理器,当当前的socket上有可读事件时,就会触发这个handler的handle_input方法。  
        char* msg = "Client connected successfully in server.";  
        peer().send(msg, strlen(msg));  
        return 0;  
    }  
  
    int handle_input(ACE_HANDLE)  
    {  
        ssize_t cnt = peer().recv(data, DATA_SIZE);  
        if (cnt <= 0)  
        {  
            ACE_DEBUG((LM_WARN, " No data received.\n")); //打印warn级别日志  
        }  
        else  
        {  
            ACE_DEBUG((LM_DEBUG, “%s”, data));  
            //在这里添加具体业务处理代码  
            char* msg = "Request is processed successfully";  
            peer().send(msg, strlen(msg));  
        }  
        return 0;  
    }  
  
private:  
    char* data;  
    static const int DATA_SIZE = 64;  
};  
typedef ACE_Acceptor<Server_svc_handler, ACE_SOCK_ACCEPTOR> ServerAcceptor;
int main(int argc, char* argv[])
{
	ACE_DEBUG((LM_DEBUG, "Test server running...\n"));
	const int PORT_NUM = 12345;
	ACE_INET_Addr addr(PORT_NUM);
	ServerAcceptor acceptor(addr, ACE_Reactor::instance());
	ACE_Reactor::run_event_loop(); //会一直不停的监听注册的事件。  
	return 0;
}

 

下面是Client_svc_handler,它与server端的类似。

class Client_svc_handler: public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH>  
{  
public:  
    Agent_svc_handler()  
    {  
        data= new char[DATA_SIZE];  
    }  
    int handle_input(ACE_HANDLE)  
    {  
        peer().recv(data, DATA_SIZE);  
        ACE_DEBUG((LM_DEBUG, “%s”, data));  
        return 0;  
    }  
private:  
    char* data;  
    static const int DATA_SIZE = 64;  
};  

typedef ACE_Connector<Client_svc_handler, ACE_SOCK_CONNECTOR> ClientConnector;  
int main(int argc, char* argv[])  
{  
    const int SERVER_PORT_NUM = 12345;  
    ACE_INET_Addr remoteAddr(SERVER_PORT_NUM, "localhost");  
    ClientConnector connector;  
    Client_svc_handler *handler= new Client_svc_handler;  
    if(connector.connect(handler, remoteAddr) == -1 )  
    {  
        ACE_ERROR(LM_ERROR, "%P|%t, %s", "Connection failed");  
    }  
    ACE_Reactor::run_event_loop();  
    return 0;  
};  

你们可能会注意到,Server_svc_handler实现了open方法,但是Client_svc_handler却没有,是因为,open方法在ACE_svc_handler中就已经有默认实现,就是将当前的handler进行注册:
        ACE_Reactor::instance()->register_handler(this,    ACE_Event_Handler::READ_MASK);
因为在服务器端接收到客户连接以后,给客户端发了一个回应,所以我们才重新实现。

总结:

这个例子只是对socket的可读操作注册处理器,在Reactor框架中,我们可以对任何的I/O操作的读或者写进行处理,也可以对系统的信号量注册处理函数。
使用ACE框架,我们就可以把重心放在业务的处理上,而不用为底层的系统调用和错误处理费太多脑筋。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值