您的位置:首页 > Web前端 > React

ACE Framework 试用报告

2014-09-26 20:46 337 查看
楼主正在上coursera上面的关于设计模式的课程. 其中作业里面需要使用ACE framework.

ACE 是Adaptive Communication Environment的简称. ACE是一个面向对象c++的框架, 他对不同操作系统关于网络操作API进行了封装提供了统一的接口.

楼主简单地用他完成了一个web server. Echo Web Server.

Reactor pattern 和 Acceptor-Connector pattern (Acceptor role).

ACE 实现了Reactor pattern 和 Acceptor-Connector pattern 这两个设计模式. 通过使用这两种设计模式, ACE达到了分离Web service建立连接代码, 事件处理代码和Demultiplexing and Dispatching Handles for Synchronous Events代码的目的.

Reactor负责分派所有的Event, 包括同一时间来自不同客户端连接请求和已经连接好的客户端发送的数据事件.

Acceptor负责处理客户端的连接请求, 当一个连接请求到达的时候, 他要初始化Stream, 并且创建一个专门处理数据事件的ACE_Svc_Handler并且把Stream作为参数传给他.

这个新创建的ACE_Svc_Handler专门负责处理客户发送过来的数据, 比如一个http GET请求.

这三个角色组合起来可以实现服务器程序的监听, 连接以及事件处理功能.

#include <string>

#include "ace/OS_NS_stdio.h"
#include "ace/Reactor.h"
#include "ace/Acceptor.h"
#include "ace/Svc_Handler.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Stream.h"
#include "ace/Synch_Traits.h"

class Echo_Svc_Handler: public ACE_Svc_Handler<ACE_SOCK_Stream, ACE_NULL_SYNCH>
{
public:
Echo_Svc_Handler(): name_()
{
ACE_OS::sprintf (this->name_, ACE_TEXT ("Connection --> "));
}

virtual int handle_input (ACE_HANDLE /*fd*/)
{
ACE_TCHAR buf[MAXPATHLEN] = {0};
ssize_t len;

len = this->peer ().recv (buf, MAXPATHLEN * sizeof (ACE_TCHAR));

if (len == -1)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("Error receiving from Echo_Svc_Handler\n")),
-1);
else if (len == 0) // Connection closed.
{
ACE_DEBUG ((LM_INFO,
ACE_TEXT ("Connection closed\n")));
return -1;
}

ACE_TCHAR return_buf[MAXPATHLEN] = {0};
ACE_OS::strcpy (return_buf, this->name_);
ACE_OS::strcat (return_buf, buf);
len = (ACE_OS::strlen (return_buf) + 1) * sizeof (ACE_TCHAR);

if (this->peer ().send (return_buf, len) != len)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("Error sending from Echo_Svc_Handler\n")),
-1);

return 0;
}

virtual int handle_close (ACE_HANDLE /*handle*/, ACE_Reactor_Mask /*close_mask*/)
{
delete this;
return 0;
}

virtual ~Echo_Svc_Handler() {}
private:
ACE_TCHAR name_[MAXPATHLEN];
};

typedef ACE_Acceptor<Echo_Svc_Handler, ACE_SOCK_Acceptor> Echo_Acceptor;

int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
ACE_Reactor* reactor = ACE_Reactor::instance();
ACE_INET_Addr local_addr(8000);
Echo_Acceptor echoAcceptor(local_addr);
reactor->register_handler(&echoAcceptor, ACE_Event_Handler::ALL_EVENTS_MASK);
reactor->run_reactor_event_loop();
return 0;
}


在ACE中, 一个Reactor需要有一个Acceptor负责处理ACCEPT事件(客户端连接请求), Acceptor在ACE中是一个ACE_Svc_Handler的工厂, 在处理ACCEPT事件的过程中, 会创建一个ACE_Svc_Handler (默认方法是operator new), 并且像Reactor注册这个ACE_Svc_Handler; 好让他处理之后来自同一客户端的数据事件.
这就解释了为什么上面的程序需要调用register_handler来注册Acceptor, 同时Acceptor的模板参数里面需要具体的ACE_Svc_Handler的类型.

感想:

使用ACE有很多好处

1. 三个角色分工明确, 代码维护性大大提高. 像上面这种简单的功能, 程序员只需要专注在事件处理就行了, 不用接触到底层的socket API.

2. Framework自带的类Reactor和Acceptor功能强大, 可以定制同步API, 线程管理策略. 还可以配置底层的传出协议. 容易测试, 也方便性能调优.

但是也有些让我写代码不舒服的地方,

1. 内存管理不对称

对于Svc_Handler, 他是在Acceptor处理ACCEPT事件时创建的, 但是却需要自己在handle_close的时候delete.

这种不对称性我觉得是一个bug的隐患. 如果是我实现这个地方, 我觉得应该提供给Acceptor的不是Svc_Handler的类型, 而是一个他的静态全局工厂对象, 而工厂对象负责统一分配回收内存, 或者使用新的c++标准中不同的smart pointer来自动管理内存.

2. framework多层的间接调用, 影响性能
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息