基于.Net的消息通讯技术研究
[摘 要]按照发送者和接受者所处的位置关系,基于windows系统的消息通讯可以分为进程内通讯和进程间通讯。进程内通讯采用发布/订阅方式进行通讯是比较合理的一种通讯方式,进程间通讯可以采用多种方式,优选了简单易用并且实用的系统消息
wm_copydata方式,将两种通讯方式在.net平台下进行集成和封装,以公用组件的方式应用于系统之中,既满足了系统的消息通讯,而且做到了模块之间的和通讯的。 [关键词].net 消息 通讯 进程
中图分类号:tg333.7 文献标识码:a 文章编号:1009-914x(2013)08-141-01 1 引言
进程内通讯在类似vs2010这样的开发工具中都进行了集成,而使用方式也有点对点、订阅/发布等多种方式;进程间通讯在windows系统中也有文件映射(memory-mapping fields)、内存共享(shared memory)、匿名管道(anonymous pipe)、命名管道(named pipe)、邮件槽(mailslots)、剪切板(clipped board)、动态数据交换(dde)、动态链接库(dll)、远程过程调用(rpc)、netbois函数、windows sockets、wm_copydata消息、消息列队等方式,每种方式有其优势和特点。
在一个系统中,既要用到进程内的通讯,又要用到进程间的通讯,而且想把系统中所有的消息通讯进行一个封装,所有除了主程序之
外的所有模块(另起进程)通过dll引用既能与其他的模块进行消息传递和消息处理。因此,需要选择一个合适的消息通讯方案。 2 方案设计
通过对目前的进程内和进程间通讯技术的研究,设计了订阅/发布式的进程内通讯方式,同时考虑到系统不存在不同主机、不同操作系统之间的进程间通讯,采用了简单实用的窗口消息方式进行通讯,使用windows的wm_copydata消息来进行消息传递。并且将两种通讯方式进行了封装,以类库的方式提供给系统中所有的模块使用。 3 系统实现 3.1 进程内通讯 3.1.1 消息的发送
通过引用消息通讯类并实例化其中的generalecfclient类,注册到消息池,将需要发送的数据封装到ecfmessage类中进行整体的发送,通过generalecfclient类中的发布方法publishmessage将该消息进行发布。
进程内通讯可分4步完成:(1)eventcommunication组件的引用;(2)generalecfclient类型的定义;(3)generalecfclient实例化及注册;(4)消息的发送:ecfmessage msg = new ecfmessage();msg.parameter = new serializabledictionary();msg.command=“ea_zhljtshow”;msg.parameter.add(”name”,this.textbox2.text);ecfclient.publishmessage
(”eiseeecfcommonclient”,msg); 3.1.2消息的接受
进程内通讯的接收端同样引用eventcommunication并实例化和注册generalecfclient类,并对其添加对事件onecfmessage的相应,该相应即是事件在接收到相应的消息以后的处理过程,程序在使用过程中可以将所有的的消息处理放到代理方法中,并做统一的区分和处理。
进程内通讯可分6步完成:(1)eventcommunication组件的引用;(2)generalecfclient类型的定义;(3)generalecfclient实例化及注册;(4)为了允许跨线程访问用户控件,定义代理private delegate void invokecallback(ecfmessage msg);(5)消息的接受及处理,ecfclient.onecfmessage += new
onecfmessagehandler(excetuecfmessage);(6)消息的处理在方法excetuecfmessage中进行,其中excetuecfmessage中的内容为: if(this != null && !this.isdisposed) { if(this.invokerequired)
{ invokecallback msgcallback = new invokecallback(excetuecfmessage);
this.begininvoke(msgcallback,new object[] { message }); return;} } //消息的处理内容 ……
3.2 进程间通讯 3.2.1 消息的发送
进程间的消息发送也是通过generalecfclient类完成,基本用法与进程内通讯一致,不同之处在于,消息的发布通过广播的方式完成,通过broadcastmessageexcept方法将携带数据的消息发送到所有windows窗口句柄,在接收端通过判断消息来源的标示id判断是否需要自己的相应。
进程内通讯可分4步完成:(1)eventcommunication组件的引用;(2)generalecfclient类型的定义;(3)generalecfclient实例化及注册:ecfclient2 = new generalecfclient(”form1”,enumcommunicationtype.win32copydata,this.handle.tostring());ecfclient2.register(),此处使用win32copydata类型数据;(4)消息的发送:ecfmessage msg = new ecfmessage();msg.parameter = new serializabledictionary();msg.command = “ea_zhljtshow”;msg.parameter.add(”name”,this.textbox2.text);ecfclient2.broadcastmessageexcept(”form1”,msg);此处使用了broadcastmessageexcept方法作为消息的广播。 3.2.2消息的接受
进程间的消息接收通过订阅generalecfclient类和重写系统的defwndproc方法来接收和处理消息。
进程内通讯可分5步完成:(1)eventcommunication组件的引用;
(2)generalecfclient类型的定义;(3)generalecfclient实例化及注册;(4)为了允许跨线程访问用户控件,定义代理private delegate void invokecallback(ecfmessage msg);(5)消息的接受及处理实际上是重写defwndproc 的过程,protected override void defwndproc(ref system.windows.forms.message m)}。 4 结论
通过研究基于.net的各类进程间及进程内通讯技术的研究,并且考虑进程间通讯的实际用处,采用了综合事件订阅/发布的进程内通讯方案和基于窗口方式的进程间通讯方式,并且将两者进行结合和封装,以dll方式提供公用组件给系统中的所有模块使用。达到了多方面的效果:第一,模块之间进行了有效的解耦,依赖性大幅度降低。第二,提供了统一标准和统一使用方法的通讯机制,每个模块的通讯,无论是进程间和进程内,只需要实例化通讯接口对外提供的接口即可。 参考文献:
[1] richter,j.周靖,张杰良. 框架设计:clr via c#[m]. 清华大学出版社. 2006
[2] eric freeman,elisabeth freeman,kathy sierra,bert bates.head first设计模式c#版[m].中国电力出版社.2007 [3] 王翔.孙逊.模式--工程化实现及扩展[m]. 电子工业出版社. 2012