组态软件作为用户可定制功能的软件平台工具,目前已经在各个行业和领域得到了广泛应用。组态软件伴随着dcs及计算机控制技术的发展而逐渐成熟进来,组件化、分布式已经成为组态软件的基本特征。优秀的组态软件大多将它的实时数据库、hmi、i/o服务器、数据服务器等几个主要部分设计成分别可独立运行的组件。这些组件可以同时运行在一台计算机内,也可以分布式地运行在不同的计算机内,通过网络等方式实现组件间的通信。这种体系结构可以让用户灵活地配置自己的系统,合理地分配各个服务器的运算负荷。
但实现组件化同时也带来了软件设计上的复杂性。特别是如何实现组件间的高效、实时、可靠地通信成为一个关键问题。
2 组件间通信技术
组件间在实现通信过程时,包括两种方式:本地方式和远程方式。在设计时,可以考虑将本地方式作为远程方式的基础。或者说,实现了本地通信,也就实现了远程通信。因为可以将组件间交换的数据通过远程方式,传送到目的机后,再通过本地方式与远程组件通信。下面我们分别讨论如何实现组件间的本地通信和远程通信。
3 本地通信
组件间实现本地通信时,在底层上要解决的本质问题上是进程间通信问题。进程间通信是一种与os密切相关的技术。本文所介绍的方法是以微软的windows操作系统为基础的。windows各个版本的操作系统都提供了丰富的进程间通信手段。从早期版本提供的管道、邮件槽、dde技术,到后来推出的com技术,以及目前最新的“.net”中提供的全新方法等。本文介绍的技术属于“传统”技术,它的基础是windows的消息传递功能,同时辅助内存文件映射和信号量技术。笔者认为这种方法有以下几个优点:
(1) 实现简便
因为涉及的技术都不很复杂,因此实现起来比较容易。
(2) 实时性高
这种方法使用的都是os的底层技术,中间环节少,运行效率高,可以实现快速数据通信。
(3) 移植性好
因为采用的是os底层技术,这种方法受os版本升级的影响很小,也很容易移植到非windows操作系统上。而某些进程间通信技术,如dde,在新版的windows操作系统上已经不再被支持。其它一些技术也因os升级在接口形式和实现方法上发生了很大变化,使应用程序受到影响。
(4) 功能可控性好
这里的可控性是指开发人员在使用一种技术时,能否有效地控制这种技术的运用。例如,开发人员在选用一种技术时,如果这种技术作了过多的封装,虽然应用简单,但要实现自己的灵活控制时就会处处受缚。
(5) 可靠性易控
这一点与上面提到的可控性是相关的。操作系统越是底层的技术,可靠性就越强。封装得越多的技术,其可靠性就越无法控制。
(6) 对系统环境的适应能力强
这个问题可以用一个简单的例子说明:用过基于com/dcom技术开发的软件产品(如:opc类软件)的用户,很多人都经历过因不同系统环境而必须面对com/dcom复杂配置的困惑。
本地通信在计算模式上仍然属于c/s结构。主要问题是如何实现多个client与server之间快速、并发式的数据交换实例。下面结合实例进行说明。
3.1 多个client与server通信实例
假设client和server是采用这种技术的客户端和服务器端程序,它们都是基于窗口的独立进程。每次进行数据交换时client向server发送一个请求报文,server收到请求报文后,再向client回复一个应答报文,如此不断往复。
因为可能有多个client与同一server同时进行快速数据交换,因此上述交互过程必须采用异步方式方能保证可靠性和并发性。为了实现方便,需要抽象一个专用于进程通信的中间件icom以供各个client同时调用。
(1) 提供3个最基本的接口
a) open() 在这个接口里icom实现的功能包括:初始化用于数据交换的内存映射文件、创建上行(client到server)和下行(server到client)事件通知的信号量对象、创建用于防止共享冲突的信号量对象,启动服务线程,同时client向server发送消息进行身份认证和注册。
b) close() client在关闭进程或断开与server的通信时调用该接口。这个接口icom要释放在执行open()方法时创建的对象资源,同时client向server发送消息执行注销操作。
c) sendmessage() client向server发送报文时调用该接口。
(2) 报文的传递过程
当client调用icom的sendmessage()方法向server发送报文时,需要使用信号量控制时序。当用sdk函数sendmessagetimeout()将报文发送给server后,通过信号量等待server的回复,一旦等到回复信号,便知道server已经将回复报文放到内存映射文件中,就可以取得该报文并以参数的形式传递给client。
为了接收对方发送的消息,server程序的主窗口类上要增加消息“wm_copydata”的映射函数。当client调用icom的sendmessage()方法向server发送报文时,server会立刻接收到wm_copydata消息,并通过消息参数获取报文信息。但是server在接收到请求报文后并不立即处理、回复,要首先用replymessage()方法对wm_copydata消息进行应答,以免对方进程发生无谓等待,然后将报文放到内部缓冲队列中,再向自身的主窗口用postmessage()发送一个通知消息,在另外一个消息映射函数中处理缓冲队列中的请求报文。server的这种处理机制是保证交互过程为异步方式的关键。这种异步机制非常重要,它可以在多个client程序与server之间进行频繁的大数据量交换时合理地分配cpu资源,避免发生“死锁”现象。
server解析请求报文的内容,将回复报文放至icom中分配的内存映射文件中,并通过信号量通知icom接收回复报文。一次完整信息交互过程完成。报文的格式由报头和数据尾两部分组成。报头为固定结构,其中要包含消息号、数据长度、client的id等信息。数据尾部分为不定长的任何内容。
4 远程通信
远程通信完全建立在本地通信的基础之上。但要增加两个专用于网络通信服务的组件:netclient和netserver。netclient和netserver也是两个完全独立的进程。以采用tcp/ip网络为例,netclient和netserver分别相当于socket client和socket server端。netclient和netserver并不关心传送的报文的内容,它们只负责网络连接的建立、报文的传输、网络通信故障时的数据缓存与恢复等。
仍结合上一节中的实例。当client程序与server进行远程数据交换时,client将与netclient运行在同一计算机内,而server与netserver运行在同一计算机内。此时icom将client的请求报文首先通过本地通信方式发送给netclient,再由netclient通过网络发送给远程的netserver,然后由netserver通过本地通信方式传送给server。而server的回复报文的传送过程正好相反。
在实际开发产品时,netclient和netserver可以设计成为更具广泛意义上的网络服务组件。除了支持tcp/ip网络,还可以支持udp/ip、串行通信、gprs等任何一种通信形式。而无论使用哪一种通信方式对于client和server来说都是完全透明的,这也正是产品实现组件化的优势所在。
5 结束语
组件间通信技术是设计组态软件、数据通信类软件的关键技术之一。如何能够在实现快速、高效、多用户并发处理的前提下,保证可靠性、灵活性和广泛适应性,值得设计人员思考。本文介绍的技术在笔者设计的组态软件产品中多处得到运用,经过逾千应用案例的证明是成熟可靠的。
参考文献
[1] 马国华. 监控组态软件及其应用[m]. 北京:清华大学出版社,2001.
[2] brian myers,eric hamer. mastering windows nt programming,1994.