欢迎您访问我爱IT技术网,今天小编为你分享的编程技术是:【.NET可复用TCP通信层之消息分派器组件】,下面是详细的分享!
.NET可复用TCP通信层之消息分派器组件
上一篇主要讲到了Tcp通信层中的核心组件――Tcp组件的实现,Tcp组件是整个通信层的消息驱动源,甚至,可以将Tcp组件看作是我们整个服务器系统的消息驱动源,消息处理过程从这里引发。类似的消息驱动源还有发布的WebService接口、Remoting接口等。今天我们需要关注的是Tcp通信层中的“中央”组件――消息分派器组件ITcpReqStreamDispatcher,大家已经从前文的组件关系图中看到了消息分派器的大致位置和作用了,它是Tcp通信组件和消息处理器之间的“桥梁”。我们再对前文描述的通信层组件之间关系的一段话回顾一下:
“当网络(Tcp)组件从某个Tcp连接上接收到一个请求时,会将请求转发给消息分派器,消息分派器通过IDataStreamHelper组件获取请求消息的类型,然后根据此类型要求处理器工厂创建对应类型的请求处理器,请求处理器处理请求并返回结果。接下来再由网络组件把结果返回给终端用户。在消息分派器进行请求消息分派之前,可能涉及一系列的操作,像消息加密/解密、消息分裂/重组、消息验证等。”
上面的描述中已经体现出了消息分派器的主要职责,在理解了消息分派器职责的基础上,我们可以进一步来看看消息分派器的定义和实现了。
二.消息分派器组件
1.消息分派器组件接口的定义
消息分派器的接口很简单:
| 以下为引用的内容:
public interface ITcpReqStreamDispatcher : IReqestStreamDispatcher |
这个接口只有两个方法,第二个方法用于异步发送回复(即绕开Tcp组件发送回复),该方法的核心部分可以由第一个方法实现,我们把注意力放在第一个方法上,而Tcp组件与消息分派器进行交互的也正是第一个方法。我先解释一下这个方法的几个参数的含义:
RequestData是对请求消息的封装:
| 以下为引用的内容:
//从网络接收到的原始数据的封装 |
前面已经提到过,ConnectID用于标志每一个Tcp连接,IsFirstMsg用于表明是否为tcp连接建立后的第一个消息,因为我们可能需要对第一个消息进行额外的验证,比如,果第一个消息不是登录请求,就关闭该Tcp连接。
第二个参数leftData,表示RequestData.Buff中的数据经过消息分裂器分裂之后余下的数据(一条非完整的消息),这些数据被Tcp组件用来放在下一次收到的数据的头部进行消息重组。
第三个参数validation,是个ref参数,用于通知Tcp组件对消息验证的结果,如果验证失败,Tcp组件将关闭对应的Tcp连接。
该方法的返回值是回复的集合,每一个回复对应一个请求,而RequestData.Buff中的数据可能分裂成多个请求。另外要注意,有些请求可能是没有回复消息的。
在我们的Tcp组件的两种实现中,都可以看到类似下面的与消息分派器交互的语句:
| 以下为引用的内容:
//处理请求 |
2.消息分派器组件基本元素的实现
正如在实现Tcp组件之前需要构建一些基本元素,在实现消息分派器之前也是如此,用于支持消息分派器实现的基本元素包括:IDataStreamHelper、消息分裂器、消息处理器工厂、ITcpStreamDispatcherHook等。
(1)IDataStreamHelper消息分裂器
IDataStreamHelper,前文中已经提到,IDataStreamHelper用于从请求/回复消息中提取消息的“元数据”,并提供一些辅助方法,每个特定的应用,它们对IDataStreamHelper的实现可能是不一样的。IDataStreamHelper接口定义如下:
| 以下为引用的内容:
/// <summary> |
IDataStreamHeader即是我们所说的消息的“元数据”,如其名所示,它也是消息的“消息头”。请让我补充说明一下,依照我的经验,消息由消息头Header和消息主体Body组成,消息头用于存放消息的“元数据”等信息,而消息主体用于存放与特定请求相关的数据。消息头的长度固定,比如都是64字节或都是128字节。请求消息和回复消息公用相同格式的消息头。我们来看看消息头接口IDataStreamHeader的定义:
| 以下为引用的内容:
public interface IDataStreamHeader byte[] ToDataStream() ; //将消息头转化为流,流的长度位消息头的长度 |
需要解释一下TypeKey、ServiceKey、ServiceItemIndex,我们实际上将服务类型分为三级,可以举个不太恰当的例子让大家有个感性的认识。比如,生活中的衣、食、住、行可以作为不同的TypeKey,而“衣”中的春装、冬装可作为ServiceKey,而“春装”中的T恤、夹克可作为ServiceItemIndex。对于服务的类型,你可以根据自己的意愿分成任意层级,但据我的经验,通常情况下,三层已经够用了。
(2)消息分裂器
前面已经多次提到消息分裂器MessageSplitter,它用于将接收缓冲区中的数据分裂成一个个完整的消息,并且把余下的非完整数据返回,其接口定义如下:
| 以下为引用的内容:
public interface IMessageSplitter |
其中,Initialize方法中的参数都可以由IDataStreamHeader提供。leftData是余下的非完整消息的数据。SplitRequestMsgs方法返回的集合中是一条条完整的请求消息。
(3)消息处理器工厂
消息处理器工厂根据消息的类型(TypeKey、ServiceKey)创建对应的消息处理器来出来该消息,其接口定义如下:
| 以下为引用的内容:
public interface IRequestDealerFactory |
CreateDealer方法返回的IRequestDealer就是消息处理器,每一个消息处理器用于处理某种特定类型(ServiceKey)的所有请求。通常,可以将消息处理器封装成插件DLL,以实现功能服务的“热插拔”。
(4)消息处理器
消息处理器IRequestDealer定义如下:
| 以下为引用的内容:
public interface IRequestDealer event CbackRequestRecieved RequestRecieved ; |
(5)ITcpStreamDispatcherHook
ITcpStreamDispatcherHook是一个Hook,它为用户提供了一个自定义的对请求/回复消息进行操作的插入点。ITcpStreamDispatcherHook由TcpStreamDispatcher使用,用于对请求消息和回复消息进行截获,然后处理或转换这些消息,比如常用的处理/转换操作包括:加密/解密、消息验证等等。ITcpStreamDispatcherHook定义如下:
| 以下为引用的内容:
/// <summary> //验证消息,以下验证的消息是还没有被捕获的消息 |
关于这个接口中各方法的含义可以在消息分派器的实现中更好的领会!
3.消息分派器实现
在前述的基本元素的基础上,实现消息分派器非常简单,我们来看其核心方法DealRequestMessage的实现源码:
| 以下为引用的内容:
private IMessageSplitter curMsgSplitter=new MessageSpliter() ; public ArrayList DealRequestMessage(RequestData requestData, out byte[] leftData, ref RequestValidation validation) if(! verified) this.AddRespondToList(respondList ,this.curMsgHelper.GetRespondWhenFailure(theData ,ServiceFailureType.InvalidMessge)) ; return respondList; |
如果你是一直按顺序读下来的,理解上面的实现一定不成什么问题。到这里,Tcp通信层的所有重要的设施基本都已介绍完毕,最后,给出了提示,即,在你的应用中,如何使用这个可复用的Tcp通信层。步骤如下:
(1)实现IDataStreamHelper接口。
(2)实现IReqestStreamDispatcher接口,如果采用的是Tcp协议,则可直接使用参考实现TcpStreamDispatcher
(3)实现各种请求处理器,这些处理器实现IRequestDealer接口。
(4)实现IRequestDealerFactory接口。
接下来,还有什么?其实,还有很多,都可以提高到框架的层次,以便复用。比如,前面我们处理消息都是基于流(byte[])的形式,在此基础上,我们可以更上一层,采用基于对象的形式――即,将请求消息和回复消息都封装成类,这就涉及了流的解析(流=>对象)和对象序列化(消息对象=>流)问题;另外,我们甚至可以将Tcp用户管理纳入到框架的高度,以进行复用,比如,通常基于Tcp服务的系统都需要管理在线的Tcp用户,并记录Tcp用户请求服务的具体信息、在线时间等,这些经过良好的分析概括都可以提高到复用的高度。以后有时间,我会将这样的经验和大家分享。
最后,把EnterpriseServerBase类库中的Network命名空间中的源码和大家共享,希望对大家有所帮助!(另,该命名空间中已经包含了上述的基于对象的消息和Tcp用户管理的可复用组件)。
以上所分享的是关于.NET可复用TCP通信层之消息分派器组件,下面是编辑为你推荐的有价值的用户互动:
相关问题:tcp ip协议中,除了应用层加密之外, 有没有哪一层...
答:有很多,因为TCP/IP是借鉴于OSI的协议族,继承了OSI(开放系统互联参考模型)的开放性,所以很多不同公司制定了自己的安全协议。 举几个常见的: 1.SSL安全套接层协议,位于在应用层和传输层之间主要提供数据安全传输,提供数据完整性。 2.HTTPS... >>详细
相关问题:如何在silverlight下进行net.tcp通信操作配置
答:1:安装IIS 2:安装frmwork4.0 3:安装Silverlight_4_Toolkit_April_2010.msi 4:建创网站的虚拟目录 5:从开发机拷备System.ServiceModel.DomainServices.Hosting和System.ServiceModel.DomainServices.Server到生产机的C:\WINDOWS\Microsoft.NET\as... >>详细
相关问题:有个Java 项目,通过Socket Tcp长连接通信方式向服...
答:你这消息头、消息体的结构格式都定下来了,总长度就是固定的啊?消息体的长度不是一共2+2+4+1=9个字节么?消息格式肯定要按照服务端的要求进行发送,明显服务端不是java的程序。。但是java里是没有Unsigned Integer这种数据类型的(java的stream... >>详细
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
