前言
最早看到ACE是2年前(2003年)的事情,当时是下了一本《C++网络编程》来看,但是因为当时对网络编程的理解不深,草草翻了几页,觉得比较晦涩,就没有再看下去。一直到了2005年11月,因为需要编写一个性能、结构良好的服务器,于是就购买了《C++网络编程》1、2来看,到了现在,这个服务器基本成形,剩下的就是再添加业务逻辑,回顾学习使用ACE的经过,觉得还是记录下来比较好,就有了这个系列的文章。我是2001年开始从事编程工作,一直使用C C++作为开发语言,因为工作的原因,一直没有涉及网络编程的任务,所以,这些文章肯定会有BUG,您可以通过回帖跟我交流。
编写稳定、高效、良好结构的服务程序的要求
一般来说,经过了4~5年的程序编写工作,功能的实现基本不是太大的问题,通过查找类似的代码、算法书籍等,都能实现所需要的功能,这时,对于程序员来说,编写稳定、高效、良好结构的代码就成了首先应该考虑的问题。对于一个运行在Windows Server上的服务程序,一般的步骤如下
创建一个socket句柄 将其绑定到指定的端口 开始监听 进入一个循环 等待客户端的连接并接受它 使用接受得到的进行业务逻辑的处理编写这样的一个服务器程序不是十分困难,例如实现一个简单的WEB服务器,它仅仅读取指定的文件并返回,也许只需要不过100行左右的代码,而其他的,包括
- 选择何种网络编程模式,在Windows上,有select、事件通知、异步读写等模式。
- 有效的内存管理
- 各种容错性的处理
- 统一的有效的Log机制
- 服务器的配置,例如端口的改变,默认缓存的大小等
- 代码的结构划分、功能分离等
ACE为就是为了解决这些问题而产生的一套C++中间件,ACE不能直接完成我们所需要的功能,但是它为完成我们所需要的功能提供了大量的支持,除此而外,ACE还有一个可移植性的重要特色,鉴于我并没有接触过移植方面的工作,所以这些就不是本系列文章所要探讨的内容。
ACE的功能概述
ACE从功能上大致分为如下几个方面
ACE OS 层
ACE OS 层封装了平台相关的函数和定义,例如 ACE_OS::strlen,ACE_OS::closesocket 等,这些封装的意义在于使ACE做到与平台无关,一个比较好的例子是 socket 的定义,在 Linux 上为 int 类型,在 Windows 上为 SOCKET 类型,而ACE的 socket 定义是 ACE_Hanlde,它在不同的平台有不同的解释。ACE OS 层是所有 ACE 其他功能的基础。
ACE 结构对象化层
这个层提供了一系列的C++类封装平台相关的结构,一个比较好的例子是 ACE_INET_Addr,它封装了 sockaddr 结构,提供了诸如 get_port、get_host_name 等方法来使相关的操作更加容易。
ACE 操作系统对象的封装
操作系统对象例如 内存文件映射、线程、锁等,ACE 通过相应的类来提供对这些操作系统对象的封装
ACE 网络编程模式
对于每一个操作系统,都会有数种不同的网络编程模式,他们有的高效、有的易于编写,但总的来说,服务器的编程基本上可以划分成反应式(Reactor)和前摄式(Proactor)两种,反射式一般是基于同步的操作,前摄式一般基于异步的操作,ACE 提供了 ACE_Reactor 类和 ACE_Proactor 类封装了这两大类的编程模式,在大类下,又通过类继承提供了更加详细的实现。
ACE 服务器配置
ACE 通过 ACE_Service_Config 提供了服务器的配置功能。
ACE 工具类
例如,ACE 提供了诸如 ACE_Message_Block、ACE_Message_Queue 等类封装了读写的缓存操作。
开始写代码的地方
如同我从DOS转到Windows编程的时候找不到可以开始写代码的地方一样,ACE 也需要开发人员进行一定的学习,ACE的使用者了解它为开发网络程序提供了哪些功能。根据我的理解,使用ACE编写网络程序,一般需要做如下的几个工作:
- 选择一种网络编程模型,即是用 ACE_Reactor相关的还是用 ACE_Proactor相关模式。(事实上,ACE本身更提倡配置网络编程模式,也就是在发布的时候通过配置文件来确定使用何种编程模式,一个这样的例子是 $ACE_ROOT/apps/JAWS2,这是一个基于 ACE 的 WEB 服务器实现,它通过一个 策略 类来动态选择网络编程模式)
- 理解 ACE_Service_Config 框架,并根据该框架的要求编写相关的类(这个工作实际上是比较机械的,大多数程序都差不多)
- 编写自已的业务逻辑类,将其嵌入到使用的框架中(这是需要ACE的使用者来编写的,也就是开始写代码的地方),一般来说,我们的业务逻辑类总是从某个 ACE 类派生重载相应的方法,或是作为某个 ACE 派生类的成员。
其他的知识
ACE 并不是一个类似于 COM 组件的功能类,这样的组件提供某种功能,我们直接调用它的某个方法以完成我们自己的功能,ACE 是一个中间件,它只是让我们的编程工作更加简单,所以,要求ACE的使用者必须了解 网络编程的方法,以 ACE_Proactor 框架为例,在Windows下,它是基于完成端口的异步读写的实现,如果不了解异步编程的相关概念方法,就不能很好的使用这个框架。
ACE 和 MFC
在Windows下编程,就不能不涉及到MFC,通过编译时候的一些设置,ACE可以与MFC兼容,但是,将两种风格迥异的类库集合到一起,总是给人一种不伦不类的感觉,事实上,我在编写 MFC 程序的时候,总是避免使用 STL 的相关类,ACE 也是一样,对于用户界面的解决方法,我是创建一个基于MFC的界面程序,它通过SOCKET与基于ACE的服务器连接,进行相关的设置,而基于ACE的服务器程序,总是一个控制台的程序或者是一个 Service 程序,这样,编程的工作会有比较大的简化。