linux 通信中间件开发概要设计(2)

2020-04-15 05:03

错误!未指定书签。

2 概述

2.1 系统概述

通信中间件是一个协议层,它建立在已有的传输层协议(TCP或UDP)的基础之上,如图2-1所示。中间件为应用层提供API接口,实现数据收发等功能,但是它提供比传输层更多的特征。在本系统中,通信中间件模块提供了大数据传输(单次传输最多可达20M字节)、可靠多播、选择多播等等。

应用层调用Socket函数或通信中间件提供的通信函数,实现应用程序的互相通信服务函数调用对传输层的Socket函数调用进行包装整合,提供更多的通信特征通信中间件层服务函数调用为应用层(或通信中间件)提供各种Socket函数调用,实现端到端通信传输层(TCP、UDP协议)服务函数调用屏蔽底层硬件的差异,在IP的层面上实现网络的互联互通网际层(IP协议)服务函数调用网络接口层(在网卡内实现)实现物理层和链路层的分帧,重组功能

图2-1 通信中间件在协议栈中的位置及其功能

通信中间件模块的功能需求主要有以下几项: 2.1.1 可靠通信和不可靠通信

通信中间件需要实现两种可靠性级别的通信方式,这两种通信方式都建立在不可靠的传输层协议(UDP)之上。不可靠通信需要把大块数据(在下文中,如果不至于引起混淆,我们可能将“大块数据”不太严格地称之为“文件”或“消息”)进行分片传输,因此每小片数据都必须带有序列号,以便接收端能够重新组装。可靠通信除了要进行数据分片处理外,还要求接收端在收到首片数据和收齐整个文件后向发送端发出ACK确认。如果出现

第 3 页 共 39 页

错误!未指定书签。

数据分片丢失,则两种级别的通信方式都需要向发送端发送NAK,以便发送端重传丢失的数据。

2.1.2 异步发送和乱序接收

通信中间件的数据传输模式是异步发送和乱序接收。所谓异步发送,是指发送端的应用程序将大块数据(文件)交给中间件以后便立即返回,继续处理应用层的事务逻辑。中间件自身维护着一个发送任务列表,真正的数据发送过程由中间件控制,与应用层无关。所谓乱序接收,指的是同一时间允许多个发送端向接收端发送数据,因为数据是分片的,所以接收端在一段时间内收到的数据可能属于不同的发送者,这些数据片是互相交叉的。因此中间件必须维护一个接收缓冲池,将属于不同任务的数据放到各自的地方,而不至于互相混淆。 2.1.3 选择多播

通信中间件需要实现一对多的通信方式,即一个发送者对应多个接收者。通常可以利用IP多播技术达到这一目的,但是本系统对中间件提出了更高的要求,期望达到这样一种效果:接收者并不是所有加入了某一个多播组的所有成员,而是其中的一个子集,并且这个子集是可以任意指定的。在本系统当中,这种通信方式被称为选择多播。 2.1.4 按组名多播

IP多播技术是借助D类IP地址实现的,每个多播组都用一个D类IP地址(224.0.0.0~ 239.255.255.255)来标识。显然,IP地址不方便人们记忆,也不利于实现多播通信对应用层的完全透明,因此中间件必须实现一种类似于域名的机制,用一个字符串形式的多播组名来代替多播IP地址。

2.2 设计约束

功能需求约束:从整体上看,通信中间件的设计必须实现用户需求说明书中所要求的所有功能,如通信的可靠性级别、异步发送、乱序接收、选择多播、按组名多播等。其实现方式则可由开发人员自由选择。

独立性和通用性约束:通信中间件应当是一个相对独立的子系统,不应当向具体的应用层程序提出过多要求,不应当实现明显只针对特定应用的函数接口。整个中间件必须是一个尽可能通用的平台,各种不同的应用程序能够在上面运行良好。

第 4 页 共 39 页

错误!未指定书签。

模块化约束:通信中间件本身是一个比较大的子系统,为了方便开发和调试,中间件必须有良好的模块化。模块之间尽量独立,模块之内功能尽量单一。

2.3 设计策略

扩展策略:因为通信中间件是一个相对独立和通用的子系统,为了更好地实现通用性,各个功能模块和函数接口都应当是可扩展的。一些功能函数应当定义一些将来可能用到的参数,尽管这些参数所规定的功能在当前版本中不需要实现,但是必须考虑到以后的扩充。

第 5 页 共 39 页

错误!未指定书签。

3 方案选择

3.1 备选方案1——通信函数库

这种方案的思路是将所有通信功能实现为一个函数库,中间件向应用层开发者提供API(声明各个外部接口的头文件)、静态库(.a文件)和运行时动态链接库(.so文件)。应用层的程序经过编译链接以后,通信中间件将成为应用程序的一部分,整个系统运行的时候只有一个进程。这样做的优点是内存拷贝次数比较少,效率相对较高。缺点是应用层与中间件层结合太过紧密,不利于实现通信中间件的通用化,并且一旦应用程序运行时出现故障,难以查找故障点出在应用层还是中间件里面。

图3-1描绘了本方案的数据传输过程,图中用通信中间件提供的两个典型函数COM_unicast()和 COM_receive()为例进行说明。

应用程序(调用COM_unicast)应用程序(调用COM_receive)通信中间件(调用sendto)通信中间件(调用recvfrom)内核层协议栈内核层协议栈

图3-1 方案1的数据传输过程

3.2 备选方案2——通信守护进程+函数库

这种方案的思路是仿照Spread的实现方法,将通信中间件做成两大部分。一部分是一个独立运行的通信守护进程(Daemon),守护进程维护着发送任务队列和接收任务缓冲池,负责主机之间的数据传输。这种方案同时也提供一个函数库(包括相应的头文件,静态库和动态库),但是与方案1不同的是,这个函数库的功能比较简单,它不负责实际的数据传输工作,它只是将应用层请求发送的数据交给守护进程,和从守护进程提取接收完成的大块数据(文件)。

图3-2描绘了方案2的数据传输过程,同样用中间件API提供的COM_unicast()和COM_receive()为例进行说明。

第 6 页 共 39 页

错误!未指定书签。

应用程序(调用COM_unicast)应用程序(调用COM_receive)通信中间件函数库(调用send)通信中间件函数库(调用recv)通信中间件守护进程(调用sendto)通信中间件守护进程(调用recvfrom)内核层协议栈内核层协议栈

图3-2 方案2的数据传输过程

与方案1相比,本方案在层次上多了一层,因此在整个“应用层-应用层”数据传输过程中,多了两次内存拷贝,显然,这对效率是有一定影响的。但是这种方案也有它的优点,它实现了具体通信过程(即中间件的守护进程部分)与应用层逻辑的完全分离,使得“异步发送”和“乱序接收”得以方便的实现。同时使中间件本身获得了更好的独立性和通用性。最后一点,在软件故障发生时,它让开发人员能够准确地定位到底是应用程序还是中间件本身存在BUG。

3.3 选定的方案及理由

本系统在功能方面提出了“异步发送”和“乱序接收”的需求,如果采用方案1,会让中间件这个子系统变得异常复杂,而用方案2则可以很方便地实现,因为通信守护进程维护了发送任务列表和接收任务缓冲池。

本系统注重通信中间件的独立性、通用性和扩展性。采用的设计策略是扩展策略,选用方案2能够更好地实现这些特性。

当然,方案2会带来一些效率上的损失,但是我们可以采用一些策略来进行优化,让效率的损失降低到最低限度。比如,应用程序和通信守护进程通常运行在同一台主机上面,因此可以使用效率比较高的Unix域协议(Unix Socket API)代替因特网域协议来进行本地数据传输。

第 7 页 共 39 页


linux 通信中间件开发概要设计(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:我与企业共命运,同舟共济谋发展

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: