ESFramework介绍之(31)―― 消息分类及对应的处理器

ESFramework介绍之(35)―― IMessageTransceiver

    (本文适用于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及其相关组件关系图如下:
     ESFramework介绍之(31)―― 消息分类及对应的处理器
      
    我们看到,整个应用所有的消息收发都可以通过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实现。感谢关注!

你可能感兴趣的:(framework)