ESFramework介绍之(35)―― IMessageTransceiver

简介: (本文适用于ESFramework V0.3+)        在ESFramework介绍之(7)-- 服务器代理IServerAgent 一文中,我们详细的介绍了IServerAgent,我们已经知道,客户端与服务器之间的所有通信都可经过IServerAgent,包括要转发的P2P消息。

    (本文适用于ESFramework V0.3+)
    
    在ESFramework介绍之(7)-- 服务器代理IServerAgent 一文中,我们详细的介绍了IServerAgent,我们已经知道,客户端与服务器之间的所有通信都可经过IServerAgent,包括要转发的P2P消息。IServerAgent的主要目的是:
(1)屏蔽客户端与服务端之间的通信协议(Tcp/Udp),ITcpServerAgent、IUdpServerAgent
(2)可将异步的消息请求/回复转化为同步的方法调用。 

    客户端与服务端的所有交互都可以通过IServerAgent进行,但是如果客户A与客户B之间直接进行P2P通信了?那么A和B之间的P2PMessage就不需要经过服务器转发,即不需要提交给IServerAgent,而是交给IP2PChannel发送;如果客户A和客户B之间不能直接通信,那么A和B之间的P2PMessage就需要经过服务器转发。

    为了对上层应用屏蔽P2PMessage是通过服务器转发器的还是通过IP2PChannel直接发送的,ESFramework引入了IMessageTransceiver,它的智能在于,如果P2PMessage可以通过IP2PChannel直接发送,则将其交给IP2PChannel,否则将其提交给IServerAgent由服务器转发。这样应用只需要直接使用IMessageTransceiver提交(发送)消息就可以了,而不用关心下层的消息路由途径。
    IMessageTransceiver接口定义如下:

    public   interface  IMessageTransceiver
    {
        
///   <summary>
        
///  如果超时仍然没有回复,则抛出超时异常
        
///  如果dataPriority != DataPriority.CanBeDiscarded ,则checkRespond只能为false
        
///   </summary>      
        NetMessage CommitRequest(NetMessage requestMsg ,DataPriority dataPriority ,  bool  checkRespond);        

        IP2PChannelManager P2PChannelManager{
set  ;}
        IServerAgent ServerAgent{
set  ;}
        IPassiveHelper PassiveHelper{
set  ;}
    }

    IMessageTransceiver及其相关组件关系图如下:
     
      
    我们看到,整个应用所有的消息收发都可以通过IMessageTransceiver进行,而不用在去操作IServerAgent了(当然,我们可以完全在IServerAgent的基础上构建应用,而不关心IMessageTransceiver的存在)。当有消息发送/提交(无论是基本消息、功能请求消息、还是P2P消息)时,直接提交给IMessageTransceiver即可。IMessageTransceiver对要发送的消息采取如下流程:
(1)如果是非P2P消息,则直接提交给IServerAgent。
(2)如果是P2P消息,然后向p2PChannelManager查询针对目标客户的P2PChannel是否存在,如果存在,则直接通过P2PChannel发送;否则,就提交给IServerAgent进行转发。
    以下是IMessageTransceiver实现这个流程的代码:

        public  NetMessage CommitRequest(NetMessage requestMsg, DataPriority dataPriority,  bool  checkRespond)
        {
            
// 通过IP2PChannel发送P2PMessage
             if ( this .passiveHelper.GetPassiveMessageType(requestMsg.Header.ServiceKey)  ==  PassiveMessageType.P2PMessage)
            {
                IP2PChannel channel 
=   this .p2PChannelManager.GetP2PChannel(requestMsg.Header.DestUserID) ;
                
if (channel  !=   null )
                {
                    channel.SendMessage(requestMsg) ;
                    
if (checkRespond)
                    {
                        
return   this .responseManager.PickupResponse(requestMsg.Header.ServiceKey ,requestMsg.Header.CorrelationID) ;
                    }

                    return null ;
                }
             }

            return this.serverAgent.CommitRequest(requestMsg ,dataPriority ,checkRespond) ;             
        }

    IP2PChannelManager组件用于管理当前客户与每个其它客户之间的P2P通道,它需要根据服务端发回的其它用户的地址、状态等信息来构建、销毁对应的P2P通道(IP2PChannel)。

    public   interface  IP2PChannelManager
    {
        IP2PChannel GetP2PChannel(
string  destUserID) ;
    }

    IP2PChannel,如其名,它是客户与客户之间P2P通信的信道的抽象,很显然,目前最常用的P2P通道是基于UDP的NAT穿透的通道,这是IP2PChannelManager的实现之一。如果可能(比如不同的客户位于同一局域网内部),我们也可以在客户之间使用基于Tcp 的P2P通道。IP2PChannel接口定义如下:

    public   interface  IP2PChannel
    {
        
void  SendMessage(NetMessage msg) ;
    }

   
    现在,使用ESFramework,我们可以在三个层次上构建你的客户端应用:
(1)直接在NetworkStream或Socket上构建,这样可以完全抛开ESFramework,但是这也需要你自己手动的处理所有麻烦的东西。
(2)在ITcpServerAgent上构建,这样ESFramework会帮你做好所有消息的收发,请求与回复的匹配,消息的优先级分类、消息的自动发送等等。
(3)在IMessageTransceiver构建,到这里,你甚至不用关心你的P2P消息是通过P2PChannel直接发送的还是通过服务器进行中转的。底层的通信方式对于你的应用是透明的。

    在后面介绍NAPT穿透时,我会给出基于NAPT的IP2PChannel实现和对应的IMessageTransceiver实现。感谢关注!

上一篇:ESFramework介绍之(34)―― ITcpServerAgent和IUdpServerAgent组件关系图

转到  :ESFramework 可复用的应用框架(序) 

 




 

目录
相关文章
|
网络协议 Java 算法
ESFramework介绍之(23)―― AgileTcp
前面已经介绍了ITcp接口,而AgileTcp就是ESFramework给出的ITcp的参考实现。在之前,我曾经讲解过模拟完成端口的Tcp组件实现和异步Tcp组件实现,在它们的基础之上,我更改了处理策略,而形成了AgileTcp,目的是更清晰的结构、更高的效率。
804 0
|
网络协议 Java
ESFramework介绍之(28)―― Udp组件
ESFramework对Tcp和Udp协议都提供了完整的支持,在ESFramework介绍之(21)-- Tcp组件接口ITcp介绍 和 ESFramework介绍之(23)―― AgileTcp 两篇文章中介绍了Tcp组件,相对于Tcp来说,Udp要简单许多,所以我在这里打算用一篇文章来介绍它。
944 0
|
容器
ESFramework介绍之(29)―― 插件公共设施 AddinUtil
(本文适用于 ESFramework V0.2+)    不知你是否还记得,前面我们讲过,ESFramework规定了插件有如下特点: (1)一个插件是一个独立的物理单元。它可以独立的提供一项完整的服务(功能),而不需要依赖于其它插件。
774 0
|
监控 网络协议 数据安全/隐私保护
ESFramework介绍之(30)―― 消息侦察者 INetMessageSpy
(本文适用于ESFramework V0.2+)    现在我们回想一下,当网络组件(Tcp/Udp组件)接收到一个消息后,这个消息会流经哪些组件,然后再通过网络组件发送出去了。如果你研究过ESFramework V0.1,你会发现,消息“行走”的路线模型可以用下图表示出来:    请求消息(路径由黑线表示)经过网络组件后,会被Hook链中的各个Hook按照特定的顺序处理,然后到达消息处理器,消息处理器处理请求消息,并给出回复消息(路径由红线表示),回复消息同样再经过Hook链,然后通过网络组件发送出去。
848 0
|
API 数据库 网络协议
ESFramework介绍之(24)―― 日志记录IEsbLogger
框架,从另外一个角度说,就是一个半成品的应用程序,既然如此,框架在运行的过程中也会遇到诸多的异常、错误情况,我们需要将这些情况记录下来,以便在发生问题时为我们的诊断提供必要的帮助。    最最开始,那还是在ESFramework的前身即EnterpriseServerBase的时候,由于当时只是将EnterpriseServerBase作为一个类库,而并没有提升到一个框架的高度,所以是没有必要为之配备一个日志记录器(Logger),就像你从来不曾看到在使用.NET类库时还必须传个日志记录器给它,以使.NET类库中的API碰到额外情况时能够记录下错误信息。
930 0
|
网络协议
ESFramework介绍之(15)-- IRAS
每个城市都对应着自己的AS,每个AS都有一组FS为之服务,而所有的AS都由一个IRAS联系/管理起来(回顾)。前面我们已经提到,所有的FS都可以是动态添加/移除的,并且FS的地址也是自由可变的。
861 0
|
C++ 索引
ESFramework网络通信框架介绍之(2)――网络通信消息NetMessage
ESFramework网络通信框架与元数据 较之C++而言,.NET是一个更加“动态”的平台,其动态能力建立在反射机制之上,而反射的基础是“元数据”。    上文已经提到过,如果一个框架要为我们的应用做更多的事情,那么这个框架必须建立更多的标准,必须对框架自己要处理的消息有更多的了解,所以,每个消息都要是自描述的,也就是说每个消息要包含它自己的“元数据”。
881 0
|
网络协议 C++
ESFramework网络通信框架介绍之(1)――网络通信消息协议接口IContract
一.ESFramework网络通信框架与字节流        通过网络通信的系统之间(如客户端与服务端的通信)要想正常交互,它们必须有“共同的语言”,这种语言就是消息协议。遵守消息协议的消息才能被我们的系统所理解。
889 0
|
存储
ESFramework介绍之(31)―― 消息分类及对应的处理器
这是一篇迟到了很久的文章,要不是今天看到Mediar朋友写的“基于ESFramewok的 客户端和客户端通迅”的文章,我也许还不会想起写这篇应该很早就发表的Blog,它可以帮助ESFramework的研究者/使用者们更好的使用ESFramework。
927 0
|
数据安全/隐私保护 网络协议 算法
ESFramework介绍之(4)――消息拦截器INetMessageHook
网络上传输的消息经常是经过加密和压缩,有的特定类型的消息可能还需要进行其它变形,ESFramework通过INetMessageHook对这些功能提供支持。需要说明的是,ESFramework对消息进行截获(Hook)处理有两种方式,一是仅仅Hook处理消息主体(Body),而不对消息头作任何变换;另一种方式是对整个消息(包括消息头和主体)都进行Hook处理。
802 0