较之C++而言,.NET是一个更加“动态”的平台,其动态能力建立在反射机制之上,而反射的基础是“元数据”。
上文已经提到过,如果一个框架要为我们的应用做更多的事情,那么这个框架必须建立更多的标准,必须对框架自己要处理的消息有更多的了解,所以,每个消息都要是自描述的,也就是说每个消息要包含它自己的“元数据”。那么,“元数据”位于消息的何处了?你一定想到了,对,是消息头(MessagHeader)。
在ESFramework中,消息NetMessage由“消息头+主体”构成,并且消息头和主体都必须实现上文讲到的IContract接口。消息头既是本条NetMessage的元数据,其中包含了诸如消息长度、消息类型等描述信息。ESFramework为了能识别每个消息的元数据,必须再建立一个“标准”,这个标准便是IMessageHeader接口。为了简化后面的计算和应用,ESFramework要求所有的消息头的长度是固定的,比如都是64字节。注意,固定消息头的长度不是必须的,但是这会降低框架的复杂度。
我们来看看IMessageHeader中包含了些什么信息:
1 publicinterfaceIMessageHeader:IContract,ICloneable
2{
3intMessageBodyLength{get;set;}//本消息主体的长度
4intTypeKey{get;set;}//请求的服务目录类型
5intServiceKey{get;set;}//请求类型
6intServiceItemIndex{get;set;}//请求细分索引
7intRandomNum{get;set;}//用于将回复与请求一一对应起来
8intResult{get;set;}//服务结果,1表示成功。其它值对应ServiceResultType
9stringDestUserID{get;set;}//接收消息的目标用户编号
10stringUserID{get;set;}//发出请求的用户编号
11boolP2PAck{get;set;}//仅仅对P2P消息有效,1表示为服务器转发P2P消息的Ack,Result反映了转发成功还是失败。Ack消息主体为null
12boolZipMe{get;set;}//控制对于本条消息是否启用压缩/解压缩,如果有些消息比较短小,则将IMessageHeader.ZipMe设为false
13}
IMessageHeader现在已经包含了比较多的内容了,其实刚开始时,IMessageHeader仅仅需要32个字节就足够,随着ESFramework的演化成长,越来越多的信息慢慢加了进来,现在IMessageHeader的长度基本上需要96字节。加进来的内容对很多应用是必须的。
比如,DestUserID表明了本条消息不是交给服务器处理的,而是要服务器转发给ID为DestUserID的用户,这为框架引入了处理“P2P消息”的能力;有时,用户可能需要发送一系列按顺序的P2P消息,如果是基于UDP,则必须要等到对方确认收到上一个消息后,才可以发送下一个消息,于是就有了P2PAck字段。基于对网络上传输的消息进行压缩是常见的要求,而有些比较短小的消息又不必进行压缩的情况,就出现了ZipMe字段,表明消息是否被压缩/解压过。
而在你的具体应用中,消息头应该包括哪些内容,由你的应用的需求来决定,比如,你的应用可能从来不需要处理P2P消息,那么在实现IMessageHeader接口时,就不需要关注DestUserID字段和P2PAck字段,并且在你的实际的消息头的字节流中也不需要为它们提供“位置”;而且在使用ESFramework装配你的应用的时候,也不用“接插”“P2PMessage处理器”。这是非常灵活的。
刚才看到的是消息头的结构,那么消息主体是什么了?在框架这一层,由于框架对所有的具体消息的主体内容一无所知,即使框架知道消息主体可以被解析为一个IContract“对象”,但是在这一层,并没有足够的信息给框架去将主体解析为IContract。所以,框架中的消息主体仍然用字节流byte[]表示,而且框架也根本不关心这个消息主体如何解析、如何处理,这些都是应用的事情。框架已经通过消息的元数据对该消息有足够的了解了。
消息NetMessage的定义如下:
1 [Serializable]
2publicclassNetMessage
3{
4publicIMessageHeaderHeader=null;
5publicbyte[]Body=null;//可以经过压缩、变换Hook
6publicobjectTag=null;//用于在将NetMessage交给IDataDealer时传递额外的信息,不影响ToStream,且很少使用
7
8publicNetMessage()
9{
10}
11
12#regionCtor,ToStream
13publicNetMessage(IMessageHeaderheader,byte[]body)
14{
15//省略实现......
23}
24
25publicbyte[]ToStream()
26{
27//省略实现......
41}
42#endregion
43
44#regionLength
45publicintLength
46{
47//省略实现......
57}
58#endregion
59
60}
Tag字段用于存放可能在后面的消息处理链中需要使用到的额外信息,比如,基于UDP时,Tag可以存放发送本条消息的客户的IPEndPoint,而这个信息可能会被后面的消息处理器用到。
RoundedMessage包含了比NetMessage更丰富的信息,从网络进口接收到的实际上是RoundedMessage,有时消息分配器或处理器可能需要用到类似ConnectID这样的信息。
在客户端和应用这一层,NetMessage可以向下转换,因为此时,我们已经知道了消息主体的结构,这个消息主体已经可以被解析为IContract了,所以NetMessage可以转换为Message:
Message
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> publicclassMessage
{
privateIMessageHeaderheader;
privateIContractbody;
publicMessage(IMessageHeadertheHeader,IContracttheBody)
{
//省略实现......
}
publicNetMessageToNetMessage()
{
//省略实现......
}
#regionToStream,GetStreamLength
publicintGetStreamLength()
{
//省略实现......
}
publicbyte[]ToStream()
{
//省略实现......
}
publicvoidToStream(byte[]buff,intoffset)
{
//省略实现......
}
#endregion
#regionHeader,Body,MessageHelper
publicIMessageHeaderHeader
{
//省略实现......
}
publicIContractBody
{
//省略实现......
}
#endregion
}
可以看到,
NetMessage已经是一个完全的面向对象的消息了。而至于主体到底含有什么具体的内容,还需要对主体IContract向下转换到具体的协议上才行。这通常是消息处理器的工作。
关于消息处理器和处理器工厂的介绍,请留意下篇文章。
ESFramework介绍之(3)――消息处理器和处理器工厂
上一篇:ESFramework介绍之(1)――网络通信消息协议接口IContract
转到:ESFramework 可复用的通信框架(序)
分享到:
相关推荐
消息部分: 1.ESFramework介绍之(1)――网络通信消息协议接口IContract <br>2.ESFramework介绍之(2)――网络通信消息NetMessage<br> 3.ESFramework介绍之(3)――消息处理器和处理器工厂 <br>4....
进程间通信之消息队列 ( message queue ) 消息队列是消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....
主要示例在C#中的SendMessage,PostMessage,包含两个示例,一个资料文档,希望受用。 在C#中 API 消息处理 SendMessage PostMessage 进程通信 发消息 实例 文档资料
网页消息通信 Message communication for web
Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制
“消息队列”安装期间,管理员确定哪些服务器可以互相通信,并设置特定服务器的特殊角色。构成此“消息队列”网络的计算机称为“站点”,它们之间通过“站点链接”相互连接。每个站点链接都有一个关联的“开销”,它...
Windows进程之间是相互独立的,通过Windows消息机制,我们可以在进程之间进行通信,适合一台电脑的windows平台下进行消息交换,该例是两个winform之间通过windows消息发送和接收数据。 1、进程间通信 2、SendMessage...
精通Flex 3.0――14.1.1 LCDS与服务端通信方式介绍 精通Flex 3.0――14.1.2 ActionScript与Java数据类型的转换 精通Flex 3.0――14.1.3 LCDS的内容结构 精通Flex 3.0――14.2 一个最基本的LCDS应用 精通Flex 3.0――...
在windows操作系统中,消息框是用于给用户一些提示或警告的窗口。例如,消息框能够在应用程序执行某项任务过程中出现问题时通知用户。下图所示的对话框警告用户输入了一个不合法的文件名。
c# winform,设置为非活动窗体,类似软键盘。 获取当前活动的窗体,向窗体内的控件通过postmessage发送消息,或键盘消息
在linux下对消息队列简单的介绍
消息中间件message的设计,桂贤君,,本文先从总体上介绍了消息中间件的3个特点。接着系统介绍了message消息中间件的设计,结构和两种通信模式。然后分别介绍了message中间
实现网络消息信史服务的程序,程序很简单,实用。
资源包含两个源程序,里面是借用MFC的消息通信实现简单的两个进程间通信,嗯主要是通过SendMessage或PostMessage,功能实现简单便捷。
进程的管道通信 编制一段程序,实现进程的管道...Child2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收子进程P1发来的 消息,然后再接收子进程P2发来的消息。
练习说明:使用postMessage可以在iFrame、父子窗口、跨页面等,之间相互传递消息。 你好,我是TKCB-GO,一个有着游戏策划梦想,却沦为程序员的游戏家,这是我的技术博客:www.tkcb.cc 技术博客网站里面,除了我的...
Windows下应用程序的执行是通过消息驱动的。消息是整个应用程序的工作引擎,我们需要理解掌握我们使用的编程语言是如何封装消息的原理。
Java+Message+Service+JMS+java消息服务
iframe+postMessage实现跨域通信 window.postMessage()方法安全地启用Window对象之间的跨源通信;例如,在页面和它产生的弹出窗口之间,或者在页面和嵌入其中的iframe之间。