当前位置: 首页 > news >正文

【转载】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及其相关组件关系图如下:
     
      
    我们看到,整个应用所有的消息收发都可以通过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实现。感谢关注!

转载于:https://www.cnblogs.com/fx2008/archive/2011/11/27/2265247.html

相关文章:

  • 表空间的增删改
  • cs1003:语法错误,应输入“:“
  • dsp中的gel文件
  • 代码质量与上线压力
  • 开启Apache Server Status
  • C# 禁止控件重绘(绘制)
  • 基于lucene实现自己的推荐引擎
  • ubuntu网络配置文件
  • linux 文件名中间有空格 如何复制
  • PPP协议认证
  • [转] C#代码检查工具:stylecop
  • Android的一些开源项目集锦 以备以后研究
  • session.createSQLQuery()方法去执行删除无效
  • Apache 限速模块安装笔记
  • WinCE平台下BMP转JPG代码备份1
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • CSS 提示工具(Tooltip)
  • echarts的各种常用效果展示
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • HTTP那些事
  • Iterator 和 for...of 循环
  • Laravel 实践之路: 数据库迁移与数据填充
  • maven工程打包jar以及java jar命令的classpath使用
  • Meteor的表单提交:Form
  • node和express搭建代理服务器(源码)
  • node学习系列之简单文件上传
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 程序员该如何有效的找工作?
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​插件化DPI在商用WIFI中的价值
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​如何在iOS手机上查看应用日志
  • # Apache SeaTunnel 究竟是什么?
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (4)Elastix图像配准:3D图像
  • (C#)获取字符编码的类
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (四)汇编语言——简单程序
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .Net mvc总结
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .netcore 获取appsettings
  • .NET委托:一个关于C#的睡前故事
  • //解决validator验证插件多个name相同只验证第一的问题
  • ::什么意思
  • [ JavaScript ] JSON方法
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • []新浪博客如何插入代码(其他博客应该也可以)