<<C++网络编程 卷1 运用ACE和模式消除复杂性>>
第0章 设计课题、中间件方案、ACE
为了降低耦合性,降低复杂度,提高复用性,ACE设计成了层次化体系结构。ACE被设计为两层:ACE OS Adaptation层和C++ Wrapper Facades。
(1).ACE OS Adaptation层:封装了原始的基于C的OS API,隐藏了和平台相关的细节。展示了统一的OS机制接口,供高级的ACE层使用。
(2).ACE C++ Wrapper Facades层:将OS Adaptation层提供的功能用C++类来进行封装。方便使用者调用。
(3).ACE Framework层:扩充了ACE C++ Wrapper Facades类,用高级的并发和网络编程模式,具体化了ACE中多组相关类之间的标准控制流程和合作。提供了如下框架:
(a).事件多路分离和分发框架:实现了Reactor和Proactor模式。
(b).连接建立和服务初始化框架:实现了Acceptor-Connector模式。
(c).服务配置器框架:实现了Component-Configurator模式。
(d).流框架:实现了Pipes and Filters模式。
第1章 通信设计空间
1.1 无连接协议和面向连接协议:无连接协议提供面向消息的服务。面向连接协议提供流服务,因此需要将数据分成帧。
1.2 同步及异步数据交换:请求之间有很强的关联性那就需要用同步方式。高效率传输对请求次序无要求用异步方式。
1.3 消息传递与共享内存:消息传递通过IPC机制来交换字节流和“面向记录”的数据。共享内存允许相同或不同主机上的进程访问、交换数据,就像在同一台机器上一样。
第2章 Socket API 概述
2.1 操作系统IPC机制概述:IPC分为本地IPC和远程IPC。本地IPC如:共享内存、管道、信号等。远程IPC如:Socket等。
2.2 Socket API:比较详细的介绍可以看<<UNIX网络编程>>
2.3 Socket API的局限性:
(1).容易出错的API:可以想象更多的细节意味着更高的出错几率。
(2).过于复杂的API:这个直接使用过native API的人肯定会有感触。如果不照着书本中的写,很难写出没有错误的程序。
(3).不可移植、不统一的API:每个平台都是特定平台的实现、头文件分布以及句柄类型的不一致等。
第3章 ACE Socket Wrapper Facade
3.1 概述:将非面向对象的C API用Wrapper Facade模式封装成面向对象的类。本章提到的Wrapper Facade类有:
(1).ACE_Addr类:ACE网络地址继承结构的根。
(2).ACE_INET_Addr类:封装了internet地址簇。
(3).ACE_IPC_SAP类:ACE IPC Wrapper Facade继承结构的根。
(4).ACE_SOCK类:ACE socket Wrapper Facade继承结构的根。
(5).ACE_SOCK_Connector类:这是一个工厂,它连接至一个对等的接受者,然后在一个ACE_SOCK_Stream对象中初始化一个新的通信端点。
(6).ACE_SOCK_IO类、ACE_SOCK_Stream类:封装了“数据模式”socket支持的数据传输机制。
(7).ACE_SOCK_Acceptor类:这是一个工厂,它在一个ACE_SOCKE_Stream对象中初始化一个新的通信端点。对来自“对等连接者的连接请求”做出响应。
3.2 ACE_Addr类和ACE_INET_Addr类:
3.3 ACE_IPC_SAP类:为其他的ACE Warpper Facade类提供基本的“IO句柄”操作能力。
3.4 ACE_SOCK类:ACE_SOCK派生自ACP_IPC_SAP除了支持ACP_IPC_SAP的方法外,ACE_SOCK还支持如下功能:
(1).创建和销毁socket句柄。
(2).获得本地和远程对等端的网络地址。
(3).设置和读取socket选项。比如:socket队列的长度、提供广播或者多播功能、禁用 nagle算法。
3.5 ACE_SOCK_Connector类:是一个工厂类,用来主动建立一个新的通信端。功能如下:
(1).发起一个到对等接受者的连接,并在连接建立后初始化一个ACE_SOCK_Stream对象。
(2).连接可以通过阻塞、非阻塞以及定时的方式发起。
(3).运用C++ traits,以支持泛型编程技术,从而可以通过C++”参数化类型“进行功能上批量替换。
3.6 ACE_SOCK_IO类和ACE_SOCK_Stream类:ACE_SOCK_Stream类继承自ACE_SOCK_IO类。ACE_SOCK_Stream封装了数据模式socket支持的数据传输机制。ACE_SOCK_Stream实例只能在ACE_SOCK_Connector或者ACE_SOCK_Acceptor中初始化。功能如下:
(1).支持数据发送和接受。
(2).支持”分散读取“操作。这个操作涉及调用者的多个缓存区,而不是一个连续的缓存区。
(3).支持"集中写入”操作。在单个操作中写入多个非连续缓存区中的数据。
(4).支持阻塞、非阻塞以及定时的IO操作。
(5).支持泛型编程技术。
3.7 ACE_SOCK_Acceptor类:是一个工厂类,用来被动的建立一个新的对等的通信端点。功能如下:
(1).接受来自对等连接端的连接,并在连接建立后初始化ACE_SOCK_Stream对象。
(2).连接可以通过阻塞、非阻塞以及定时的方式接受。
(3).支持泛型编程技术。
第4章 网络日志服务程序的实现
4.1 概述:大多数网络程序都需要执行以下行为:
(1).主动/被动建立连接。
(2).和对等应用程序进行数据交换。
(3).管理数据缓冲区。
(4).整编/解编 “类型化” 数据。使得数据在各类异中系统中都得以正确处理。
4.2 ACE_Message_Block类:实现了Composite模式,功能如下:
(1).每一个ACE_Message_Block都带有一个指针,指向带引用计数的ACE_Data_Block,而ACE_Data_Block指向和消息关联的实际数据。这样我们可以灵活、高效的共享数据,并能降低内存复制带来的额外开销。
(2).允许多条消息连接在一起,形成一个单链表,从而支持复合(composite message)数据。这种复合数据可用于多态链表,也可用于可以高效的 “添加/删除" ”消息头/尾“的层次化协议栈。
(3).允许将多条消息连接在一起,形成一个双链表,构成ACE_Message_Queue的基础。
(4).将”同步“和”内存管理“特性作为”无需修改底层ACE_Message_Block实现,应用程序就可以改变的特征来对待。
4.3 ACE_InputCDR类和ACE_OutputCDR类:功能如下:
(1).为这些(原始类型:布尔、8,16,32,64位整数、浮点数、字符、字符串;由原始类型组成的数据)数据类型提供整编/解编操作。
(2).“<<"插入和 ">>"提取运算符可用于原始数据类型的整编和解编操作,使用语法和C++输入输出一样。
(3).在内部使用ACE_Message_Block链,以避免昂贵的内存复制操作。
(4).利用CORBA CDR的”对齐“和”字节次序“规则,避免昂贵的内存复制和字节交换。
(5).提供优化的”字节交换“代码,在常见平台上使用内联汇编指令,在其他平台上使用标准的hton系列函数。
(6).支持8位字节缓冲区的”零复制“整编和解编。
(7).在不将ASCII或UNICODE用作原始字符集的平台上,用户可以定制字符集转换器。
第5章 并发设计空间
5.1 循环、并发、反应式服务器:
(1).循环式服务器:在处理后续请求前,会完整的处理每一个客户请求。因此适合短期服务和不经常使用的服务。
(2).并发式服务器:可同时处理多个客户请求。适合IO操作频繁和执行时间会变化的服务。
(3).反应式服务器:几乎是同时处理多个客户请求,虽然都是在一个线程中完成。这种模式会增加编程的复杂性,而且可靠性和性能也会降低。特别不适合IO频繁的服务。
5.2 进程与线程:进程间通讯的代价是昂贵的,一般要OS介入。而线程间通讯不需要。另外进程创建和销毁的代价也比线程大。
5.3 进程、线程创建策略:
(1).急式创建:在服务器创建期间,创建一个或多个线程(进程),形成一个线程(进程)池。半同步/半异步(Half-Sync/Half-Async)模式:将来自“IO层”的请求,向上提供给线程池中的工作者线程;领导者/跟随者(Leader/Fllowers)模式:多个线程轮流共享一组事件源,以对这些事件源上发生的服务请求进行检测、多路分离、分发和处理。
(2).随需创建:“客户连接”、“数据请求”到来时创建新的线程。优点是资源消耗降低。
5.4 用户、核心及混合线程模型:
(1).N:1用户线程模型:在用户层实现的线程。内核不知道线程的存在。因此一旦一个线程阻塞则整个进程阻塞,且在多CPU机器上只能获得一个CPU。
(2).1:1核心线程模型:在内核中实现的线程。创建、销毁等操作的开销比较大。
(3).M:N混合线程模型:上面两种模式的组合。
5.5 分时及实时调度级别:
(1).分时调度:基于优先级、公平、抢占、时间片。
(2).实时调度:轮流、先进先出。
5.6 “基于任务”与“基于消息”的体系:并发体系是联系以下要素的纽带:CPU、“数据”和“控制”消息、执行任务的服务。
(1).基于任务的并发体系:同一个任务可能由多个线程或者CPU处理。代表性:生产者/消费者。
(2).基于消息的并发体系:同一个任务自始至终都由一个线程或者CPU处理。代表性:一个连接一个线程、线程池。
第6章 操作系统并发机制概述
6.1 同步事件多路分离:比如select、poll、epoll等函数,都是OS提供来进行事件多路分离的。用于构建反应式服务器。
6.2 多进程机制:(只是对进程的简单介绍)
6.3 多线程机制:(只是对线程的简单介绍)
6.4 同步机制:同步机制包括互斥锁、读写锁、信号量和条件变量。
6.5 OS并发机制的局限性:强制性;容易出错;不可见副作用;不可移植性。
第7章 ACE同步事件多路分离Wrapper Facade
7.1 概述:事件多路分离可以实现“反应式服务器”,可以看做是轻量级的“多任务”:一个单线程服务器以轮流方式和多个客户通信。这里将系统提供的native API封装成如下三个类:ACE_Handle_Set、ACE_Handle_Set_Iterator、ACE::select()
7.2 ACE_Handle_Set类:用Wrapper Facade模式对fd_set封装。提供以下功能:
(1).简化fd_set和select函数在各个OS平台上的使用,从而提高“事件驱动型”应用程序的可移植性、易用性以及类型安全性。
(2).在增加、删除句柄时,自动跟踪、调整fd_set中“和大小相关“的值。
7.3 ACE_Handle_Set_Iterator类:该类实现了Iterator模式。提供了连续访问聚合对象中的元素的方法,但不暴露对象的底层结构。
7.4 ACE::select()方法:对native API select进行了包装。
第8章 ACE进程Wrapper Facade
8.1 概述:ACE对系统提供的操作进程的native API进行封装,提供如下三个类:ACE_Process、ACE_Process_Options、ACE_Process_Manager。
8.2 ACE_Process类:用Wrapper Facade模式,ACE_Process类对不同OS进程API的差异进行了封装。提供了统一、可移植的方法。支持如下功能:
(1).创建和终止进程。
(2).在进程退出时保持同步。
(3).访问进程属性信息,如进程ID等。
8.3 ACE_Process_Options类:该类对进程属性(程序映像、打开的IO句柄、访问显示设备、工作路径、进程关系、安全属性)进行了统一封装。支持如下功能:
(1).允许应用程序指定想要的“进程控制信息”。
(2).允许进程控制项,根据平台的改变而进行扩展。
(3).提供了一种去耦机制,使得ACE可以提供这些功能,但不影响“进程创建”接口。
8.4 ACE_Process_Manager类:该类不仅具备了ACE_Process类的可移植性和强大威力,而且可将多组进程作为一个单元进行管理。支持如下功能:
(1).保存内部记录,管理和监视ACE_Process类创建的多组进程。
(2).允许一个进程创建一组进程,并且,在继续执行自己的处理前,必须等待这一组进程退出。
第9章 ACE线程Wrapper Facade
9.1 概述:ACE对线程的封装提供三个类:ACE_Thread_Manager、ACE_Sched_Params、ACE_TSS。
9.2 ACE_Thread_Manager类:用Wrapper Facade模式,ACE封装了线程在不同OS上语法和语义上的多样性。支持如下功能:
(1).一次创建一个或者多个线程,每一个线程执行一个应用程序制定的函数。
(2).针对每一个被创建的线程,改变其常见的线程属性如优先级、线程栈大小等。
(3).创建并管理一组线程,形成一个有机体,称为“线程组“。
(4).管理ACE_Task中的线程。
(5).实现线程的协同删除能力。
(6).等待一个或者多个线程的退出。
9.3 ACE_Sched_Params类:用Wrapper Facade模式,封装了OS调度API。提供如下功能:
(1).通过一种可移植的方式,指定调度策略,如先进先出、轮询等。
(2).提供某种方式,为轮询调度方式提供分时量。
(3).提供某种方式,策略运用的范围。例如,是运行在当前进程还是当前线程上。
(4).提供一致的调度优先级表示方式。这个很重要,因为在不同的OS高值和底值表示的优先级正好相反。
9.4 ACE_TSS类:该类实现了Thread_Specific Storage模式,封装并增强了原始OS TSS API。该类提供如下功能:
(1).支持”在物理上“为线程所专有(即,私有于一个线程)、但”逻辑上“能像程序中全局变量那样访问的数据。
(2).使用C++的”委托运算符“ operator->(),来提供”线程专有“的只能指针。
(3).封装了”和TSS对象相关联“的键的管理。
(4).在”本身缺乏足够TSS支持“的平台上,ACE_TSS高效地模拟了TSS。
第10章 ACE同步Wrapper Facade
10.1 概述:这里涉及到的ACE类如下:ACE_Guard、ACE_Read_Guard、ACE_Write_Guard、ACE_Thread_Mutex、ACE_Process_Mutex、ACE_Null_Mutex、ACE_RW_Thread_Mutex、ACE_RW_Process_Mutex、ACE_Thread_Semaphore、ACE_Process_Semaphore、ACE_Null_Semaphore、ACE_Condition_Thread_Mutex、ACE_Null_Condition。
10.2 ACE_Guard类:ACE_Guard、ACE_Read_Guard、ACE_Write_Guard类实现了Scoped Locking技术。利用C++的构造和析构语义,保证在进入或退出一段C++代码时,可以自动获得和释放锁。
10.3 ACE互斥体类:ACE用ACE_Process_Mutex和ACE_Thread_Mutex类封装了OS提供的互斥机制。从而在系统范围和进程范围可移植的实现了非递归互斥语义。ACE_Null_Mutex为统一接口而写,其在编译时会被编译器优化掉,一般用于单线程。
10.4 ACE Readers/Writer Lock类:ACE通过ACE_RW_Process_Mutex和ACE_RW_Thread_Mutex封装了原始OS提供的“readers/writer锁"机制。
10.5 ACE信号量:ACE_Thread_Semaphore、ACE_Process_Semaphore在进程范围和系统范围对OS提供的信号量进行封装。ACE_Null_Semaphore在编译时会被优化掉。
10.6 ACE条件变量:ACE_Condition_Thread_Mutex通过封装原始的OS条件变量,提供统一,可移植的条件变量。ACE_Null_Condition和ACE_Condition_Thread_Mutex提供同样的接口,但是在编译期间会被优化掉。
附录A:ACE C++ Wrapper Facade的设计原则:
A.1 概述:
A.2 通过Wrapper Facade增强类型安全性:
(1).设计出一定会被正确使用的C++类。
(2).允许在一定范围内破坏类型安全性。
A.3 简化常见形式:
(1).将多个函数合并为一个函数。
(2).将函数合并起来,置于统一的Wrapper Facade之下。
(3).重新组织参数次序,并提供默认值。
(4).将有内在关系的对象,显式的关联起来。
A.4 通过继承结构提高设计的清晰性和可扩展性:
(1).将一维的API用继承结构来代替。
(2).将伪继承用C++继承来代替。
A.5 尽可能的隐藏平台间的差异:
(1).允许源代码支持任何有益功能。
(2).模拟出缺少的功能。
(3).通过参数化类型处理变化性。
A.6 针对效率实施优化:
(1).针对效率设计Wrapper Facade。
(2).内联影响性能的方法。
(3).在系统级工具包中避免使用异常处理。