ACE开发指南初级.docx
- 文档编号:5573159
- 上传时间:2023-05-08
- 格式:DOCX
- 页数:110
- 大小:1.11MB
ACE开发指南初级.docx
《ACE开发指南初级.docx》由会员分享,可在线阅读,更多相关《ACE开发指南初级.docx(110页珍藏版)》请在冰点文库上搜索。
ACE开发指南初级
ACE开发指南(初级)
文档信息
作者
郑明智
创建日期
2006-12-19
版本
1.0
部门名称
开发部
修订文档历史记录
日期
版本
说明
作者
2006-12-19
1.0
Reactor
郑明智
2006-12-27
1.1
增加Proactor的内容
郑明智
2006-12-28
1.2
增加ACETask的内容
郑明智
1.介绍
1.1目的
本指南作为使用ACE框架开发应用程序的参考,以期能够对使用ACE框架的同事有所帮助。
1.2文档协定
本文档的书写遵循公司定义的文档规范。
本指南写作时,ACE最新的稳定版本为5.5版。
本指南中观点和代码并不保证适用于后续的ACE版本。
本指南旨在帮助新手入门,如果您已对ACE有一定使用经验并想更深入了解ACE,建议您阅读ACE的相关书籍。
1.3阅读者建议
本指南假定阅读者有C++的开发经验和通信程序的开发经验,文档中C++及Socket等开发知识及相关概念不再赘述。
1.4术语说明
C/SClient/Server客户端/服务器架构
Client客户端
Server服务器
ACE自适配通信环境(AdaptiveCommunicationEnvironment)
Reactor反应器,高效的事件多路分离和分派提供可扩展的面向对象框架
Proactor前摄器
aio异步I/O
AsynchronousI/O异步I/O
EpollLinux从2.6开始支持的异步事件I/O技术
1.5翻译约定
Method/Function方法
NestedClass内部类
Callback回调
HookMethod挂钩方法
Handle句柄
Template模板
Daemon守护
Override/Overwrite覆盖
Overload重载
1.6相关资料
ACE-5.5.zip
MagicC++3.5
1.7参考文献
[1]ACE程序员指南–网络与系统编程的实用设计模式
[2]C++网络编程(卷1)运用ACE和模式消除复杂性
[3]C++网络编程(卷2)基于ACE和框架的系统化复用
[4]ACE自适配通信环境中文技术文档–中篇ACE程序员教程
[5]ACEAPI列表
[6]ACE源代码
1.8补充说明
[1]本文档中提到的资料,工具,代码都放在了相关资料放在\\192.168.0.20\upload\开发部\技术组\ACE目录下。
[2]如果您发现本指南有错误或者疏漏,请通知作者修改,以使本指南能够更好的帮助大家。
2.ACE简介及环境搭建
2.1ACE简介
ACE自适配通信环境(AdaptiveCommunicationEnvironment)是面向对象的框架和工具包,它为通信软件实现了核心的并发和分布式模式。
ACE包含的多种组件可以帮助通信软件的开发获得更好的灵活性、效率、可靠性和可移植性。
ACE中的组件可用于以下几种目的:
✓并发和同步
✓进程间通信(IPC)
✓内存管理
✓定时器
✓信号
✓文件系统管理
✓线程管理
✓事件多路分离和处理器分派
✓连接建立和服务初始化
✓软件的静态和动态配置、重配置
✓分层协议构建和流式框架
✓分布式通信服务:
名字、日志、时间同步、事件路由和网络锁定,等等。
上面是比较官方的介绍。
总之,如果你想用C++实现一个通信程序,而你又不想纠缠于Windows/Linux等各平台不同的Socket细节,那就可以考虑ACE框架。
ACE经过10余年的开发,已经不仅仅是通信的包,还实现了很多其它功能比如内存管理,文件系统管理等,可以满足您大多数开发的需要。
而且ACE是被全世界很多项目采用的可以称的上是电信级别的框架。
ACE是跨平台的,完全可以在Windows上开发,运行在Linux上(当然,与Java不完全相同的是您需要重新编译链接。
而且如果您的程序使用了GUI的包,这么做是行不通的)。
ACE的简介就到这里。
当我们使用ACE开发了一些程序,对ACE有了一定的认识之后,再回过头来进一步认识ACE。
2.2本指南的主要内容
本指南的目标是ACE零基础到可以用ACE开发一些简单的C/S程序。
因此本指南的主要内容有:
1.ACE的获取编译
首先介绍如何搭建ACE开发环境的问题。
2.ACEReactor/Proactor框架
接下来本文并不打算像其它ACE的书籍从ACE历史介绍,基础机制讲起,而是直接进入Reactor/Proactor框架的介绍及使用这2个框架来开发程序,给初学者最想要的东西。
3.ACE其他机制
最后对ACE的其他框架机制等做一概要介绍,比如ACE_Task机制,线程管理,同步机制等。
2.3获取ACE
从服务器上获取ACE-5.5.zip。
或者从http:
//download.dre.vanderbilt.edu/previous_versions/下载你需要的ACE版本。
2.4编译ACE
2.4.1为什么要编译ACE
应用程序在链接及运行时需要使用ACE的库和dll文件(Windows),而你下载的包里没有这些文件或者不适合你的平台。
这时候就需要自己编译ACE。
编译一般来说需要花很长时间。
注1:
项目组的其他人或者公司里的同事可能已经有编译好的库文件,如果你不想花时间编译ACE,可以向其他人索取。
服务器上有ace5.3版本在gcc2.96/3.23编译通过的rpm文件,如果适合你的平台,直接安装即可。
注2:
下面的在Windows/Linux编译部分取自陈昕发的贴,本文做了适当修改。
文中目录等请注意修改成符合你的环境的目录等。
陈昕原贴在http:
//192.168.0.18/bbs/viewthread.php?
tid=1085&fpage=1
2.4.2在Window上编译
1.解压缩到本地目录
例:
解压缩到C:
\ACE_wrappers
2.查看安装向导
ACE有自带的安装向导文件C:
\ACE_wrappers\ACE-INSTALL.html
查看ACE-INSTALL.html文件中的BuildingandInstallingACEonWindowswithMicrosoftVisualC++章节,按照上面所写即可,下面是对此过程的总结
3.确定编译环境
本文使用的是C++.netframework1.1,以下为该编译环境下的步骤
4.新建config.h文件
由于ACE支持很多操作系统,因此必须建立一个config.h文件,在该文件包含相应的操作系统的头文件,从而让ACE知道将在什么操作系统下进行编译
进入C:
\ACE_wrappers\ace目录,新建config.h文件,在config.h文件中添加
#include"ace/config-win32.h"
如果系统为Windows98/Me,那么需要添加
#defineACE_HAS_WINNT40
如果需要使用标准C++的类库(例iostream等),那么需要添加
#defineACE_HAS_STANDARD_CPP_LIBRARY1
如果需要使用MFC(不推荐),那么需要添加
#defineACE_HAS_MFC1
5.设置环境变量
开始->运行->cmd
setACE_ROOT=C:
\ACE_wrappers
6.使用.net环境编译
打开ACE.sln,可进行debug/release编译
7.生成.lib.dll文件
生成的lib和dll文件在C:
\ACE_wrappers\lib。
2.4.3在Linux上编译
注:
该步骤使用ACE-5.4.7测试成功
1.解压缩到本地目录
例:
#pwd
/home/xchen
#tar-xzvfACE.tar.gz
2.设置环境变量
#su–
#vi/etc/profile
在exportPATHUSERLOGNAMEMAILHOSTNAMEHISTSIZEINPUTRC下加入以下两行
exportACE_ROOT=/usr/local/ACE_wrappers
exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:
$ACE_ROOT/ace
#./etc/profile
3.建立编译环境
#cd/home/xchen/ACE_wrappers
#mkdirbuild
#cdbuild
#../configure
4.配置config.h文件
../configure之后,系统会在/home/xchen/ACE_wrappers/build下建立ace/conig.h文件
在//ACEconfigurationheaderfile下行添加
#include"ace/config-linux.h"
5.编译
#cd/home/xchen/ACE_wrappers/build
#make
6.生成.so文件
生成的so文件在/home/xchen/ACE_wrappers/build/ace/.libs目录下。
2.5前行的路标
对ACE感兴趣,可以访问ACE网站:
http:
//www.cs.wustl.edu/%7Eschmidt/ACE.html
ACE的YahooGroup:
ACE开发者论坛(中文):
3.ACEReactor框架
3.1Reactor(反应器)框架
在编写通讯程序时,如果服务器需要处理多个客户端的连接,传统做法是为每个客户端创建一个进程或者线程。
在大多数情况下,这种方法是可以解决问题的。
但是,在某些情况下,进程线程创建维护并发的开销是无法让人接受的。
而ACEReactor框架通过事件多路分离器,只需要用一个进程或者线程就可以处理多个客户端的连接的事件。
而且用户程序使用Reactor框架也非常的简单,只需要做3件事情:
1)从ACE_Event_Handler派生子类,并Overwrite特定的事件虚回调方法。
(比如handle_input,handle_timeout)。
2)向ACE_Reactor类登记你刚才创建的ACE_Event_Handler子类。
3)运行ACE_Reactor事件循环。
Reactor的含义—被动反应,可以让我们理解它的精髓:
它是事件驱动的,就像Windows的事件驱动一样。
下面是ACEReactor框架的类图和描述。
ACE类
描述
ACE_Time_Value
提供时间和持续时间(Duration)的可移植,规范化的表示
ACE_Event_Handler
抽象类,其定义的挂钩(hook)方法是ACE_Reactor回调的目标。
大多数通过ACE开发的应用事件处理器都是ACE_Event_Handler的后代。
ACE_Timer_Queue
抽象类,定义定时器队列的能力和接口。
ACE含有多种派生自ACE_Timer_Queue的类,为不同的定时机制提供了灵活的支持。
ACE_Reactor
提供了一个接口,用来在ACE框架中管理事件处理器登记,并执行事件循环来驱动事件检测,多路分离和分派。
我们这里只关心ACE_Event_Handler和ACE_Reactor类。
3.1.1ACE_Event_Handler(事件处理器)
ACE_Event_Handler是ACE中所有反应式事件处理器的基类。
其接口如下所示:
方法
描述
ACE_Event_Handler()
指派与事件处理器相关联的ACE_Reactor指针。
~ACE_Event_Handler()
将其自身从反应器的通知机制中移出。
handle_input()
输入事件(如连接或数据事件)发生时的挂钩(hook)方法。
handle_output()
输出事件成为可能时(如流控制缓和或非阻塞式连接完成时)被调用的挂钩方法。
handle_exception()
异常事件(如TCP紧急数据的到达)发生时被调用的挂钩方法。
handle_timeout()
在定时器到期时被调用的挂钩方法。
handle_signal()
OS发出信号时(或是POSIX信号,或是Windows同步对象迁移到激发(Signaled)状态时)被调用的挂钩方法。
handle_close()
在其他handle_*()挂钩方法返回-1或者当ACE_Reactor:
:
remove_handler()被显式调用来解除事件处理器的登记时,执行用户定义的中止活动的挂钩方法。
get_handle()
返回底层的I/O句柄。
如果事件处理器只处理时间驱动的时间,该方法可实现为no-op(空操作)
reactor()
访问器,用于获取/设置可与ACE_Event_Handler相关联的ACE_Reactor指针。
priority()
访问器,用于获取/设置事件处理器的优先级。
在开发一个普通的C/S应用程序时,只需Overwritehandle_input()和handle_close()这2个回调方法也就足够了。
可以在Reactor的定时器队列设置定时器(参考下面的Reactor接口),当超时事件发生时handle_timeout()会来处理超时时应执行的操作。
下面讨论一下使用ACE_Event_Handler时注意的3个方面:
1.事件类型:
在向Reactor登记事件处理器的时候,必须指定事件类型。
事件类型定义在ACE_Event_Handler中,包括下面几种:
事件类型
描述
READ_MASK
指定输入事件(如数据出现在socket或文件句柄上)。
反应器分派handle_input()来处理输入事件。
WRITE_MASK
指定输出事件(如在流控制缓和时)。
反应器分派handle_output()来处理输出事件。
EXCEPT_MASK
指定异常事件(如紧急数据出现在socket上)。
反应器分派handle_exception()来处理异常事件。
ACCEPT_MASK
指定被动模式的连接事件。
反应器分派handle_input()来处理连接事件。
CONNECT_MASK
指定非阻塞式连接的完成。
反应器分派handle_output()来处理非阻塞式连接的完成事件。
可以对这些事件进行组合(|)来高效的定义一组事件。
这组事件被填充在ACE_Reactor:
:
register_handler()方法的ACE_Reactor_Mask参数。
2.挂钩方法的返回值
登记的事件发生时,反应器会分派相应的handle_*()来处理。
而这些方法的返回值需注意:
返回值
描述
0
指示反应器应继续为此事件处理器检测和分派所登记的事件。
对于需要重复处理一个事件的事件处理器(比如当有数据可读时从Socket读取数据),这种行为是常见的。
>0
也指示反应器应继续为此事件处理器检测和分派所登记的事件。
此外,如果在处理了某个I/O事件后返回值大于0,反应器将在阻塞它的事件多路分离器之前,再次在句柄上分派此事件处理器。
-1
指示反应器停止为此事件处理器检测已登记的事件。
在反应器移除此事件处理器之前,它调用事件处理器的handle_close()方法,传给该方法正在被解除登记的事件的ACE_Reactor_Mask值。
所以,我们在使用Reactor框架来开发C/S程序时,一般应在handle_*()方法里返回0。
3.清理事件处理器
handle_close()方法会在某个挂钩方法决定要进行清理时被调用。
handle_close()方法可随即进行用户定义的关闭活动,如释放内存,关闭IPC对象等。
Reactor框架会忽略handle_close()方法的返回值。
如上所述,Reactor只会在挂钩方法返回负值,或事件处理器被显式移除时调用handle_close(),而不会在IPC机制到达文件末尾或I/O句柄被本地或远程关闭时调用handle_close()。
因此,应用必须检测I/O句柄何时关闭,并采取措施。
比如,当recv()或read()调用返回0时,事件处理器应从handle_*()方法里返回-1,或调用ACE_Reactor:
:
remove_handler()。
3.1.2ACE_Reactor
ACE_Reactor是Reactor模式的核心类,Reactor模式的注册事件处理器,运行事件循环等功能都要通过这个类来进行。
ACE_Reactor实现了Façade模式,为应用程序提供了各种访问Reactor框架特性的接口。
1.初始化和析构方法:
方法
描述
ACE_Reactor()
open()
这两个方法创建并初始化反应器的实例。
~ACE_Reactor()
close()
这两个方法清理反应器在初始化时分配的资源。
2.事件处理器管理方法
方法
描述
register_handler()
为基于I/O和信号的事件登记事件处理器
remove_handler()
移除某事件处理器,使其不再参加基于I/O和信号的事件分派
suspend_handler()
暂时停止分派事件给某事件处理器
resume_handler()
恢复为先前挂起的事件处理器分配事件
mask_ops()
获取,设置,增加或者清除与某事件处理器相关的事件类型及掩码
schedule_wakeup()
将指定的掩码增加到某事件管理器的条目中,该处理器在之前必须已通过register_handler()登记过。
cancel_wakeup()
从某事件处理器的条目中清除指定的掩码,但并不移除该事件处理器
3.事件循环(Event-loop)方法
方法
描述
handle_events()
等待事件发生,并随即分派与之相关联的事件处理器。
可通过超时参数限制花费在等待事件上的时间。
run_reactor_event_loop()
反复调用handle_events()方法,直至其失败,或者reactor_event_loop_done()返回1,或者超时(可选)。
end_reactor_event_loop()
指示反应器关闭其事件循环。
reactor_event_loop_done()
在反应器的事件循环被end_reactor_event_loop()调用结束时返回1
4.定时器管理方法
方法
描述
schedule_timer()
登记一个事件处理器,它将在用户规定的时间后被执行。
cancel_timer()
取消一个或多个之前登记的定时器。
我们可以使用这两个方法来使代码具有超时特性,当超时发生时,事件处理器的handle_timeout()方法会被调用。
5.通知方法
反应器拥有一种通知机制,应用可将其用于把事件和事件处理器插入反应器的分派引擎中。
方法
描述
notify()
将事件(及可选的事件处理器)插入反应器的事件检测器中,从而使其在反应器下次等待事件时被处理
max_notify_iterations()
设置反应器将在其通知机制中分派的处理器的最大数目。
purge_pending_notifications()
从反应器的通知机制中清除指定的事件处理器或所有事件处理器
6.实用方法(UtilityMethod)
方法
描述
instance()
静态方法,返回指向单体(Singleton)ACE_Reactor的指针。
这是通过Singleton模式和Double-CheckedLockingOptimization模式来创建和管理的。
owner()
使某个线程“拥有”反应器的事件循环。
因为大部分的应用程序都需要实现Server或者Client端的内容,所以下面我们将分别实现一个Reactor的Server和Client。
ACE也提供了实现Server和Client的半成品,Acceptor和Connector框架。
3.2Acceptor(接受器)-Connector(连接器)框架
下面是Acceptor-Connector框架类的类图。
图中我们可以看到ACE_Acceptor,ACE_Connector继承自我们前面提到的ACE_Event_Handler。
然后ACE_Svc_Handler是继承自ACE_Task的,而ACE_Task其实也是ACE_Event_Handler的后代。
根据前面提到的Reactor开发3步骤,我们只需要将ACE_Svc_Handler登记到Reactor即可进行事件处理。
对我们开发应用程序而言,我们只需要关心ACE_Acceptor,ACE_Connector,ACE_Svc_Handler这3个类。
ACE类
描述
ACE_Svc_Handler
表示某个已连接服务的本地端,其中含有一个用于与相连对端通信的IPC端点。
ACE_Acceptor
该工厂被动的等待接受连接,并随即初始化一个ACE_Svc_Handler来响应来自对端的主动连接请求。
ACE_Connector
该工厂主动的连接到对端接受器,并随即初始化一个ACE_Svc_Handler与其相连对端通信。
通俗的说,ACE_Acceptor就是我们要实现的Server,ACE_Connector就是我们要实现的Client。
当Client连接到Server时,会创建一个ACE_Svc_Handler来处理事件(比如接收到数据,连接被断开等);而Server端也会为每个Client创建一个ACE_Svc_Handler来处理事件。
3.2.1ACE_Svc_Handler(服务处理器)
如上所述,ACE_Svc_Handler就是用来处理事件,那么主要需要处理那些事件呢?
1.服务创建和激活方法
方法
描述
ACE_Svc_Handler()
由接受器或连接器在创建服务处理器时调用的构造方法
open()
由接受器或连接器自动调用来初始化服务处理器的挂钩方法。
ACE_Svc_Handler已经在open方法里,把自己登记到Reactor事件循环,登记的事件类型为READ_MASK。
所以我们的代码将变得更加简单。
2.服务处理方法
方法
描述
svc()
ACE_Svc_Handler从ACE_Task继承来的svc()挂钩
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACE 开发 指南 初级