`
pwz1985
  • 浏览: 52052 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

关于socket通信 (解决“同步方式”封装异步socket)

    博客分类:
  • java
阅读更多

 

分布式系统的构建一般有两种模式,一是基于消息(如Tcphttp 等),一是基于方法调用(如RPCWebServiceRemoting )。深入想一想,它们其实是一回事。如果你了解过.NETProxy ,那么你会发现,方法调用和消息请求/ 回复实际上是可以相互转换的,.NETProxy 的实现,就是在堆栈帧和消息之间相互转换的过程。关于这方面的详细论述可以参见《.Net 本质论》一书。

  我觉得IServerAgent 是我在开发ESFramework 期间非常满意的一个想法,相信大家也会对它感兴趣的。因为它使得使用基于消息请求/ 回复的交互就像方法调用一样简单
    客户端与服务器之间的所有通信都可经过IServerAgent,包括要转发的P2P消息。它的主要目的是:
(1)屏蔽客户端与服务端之间的通信协议(Tcp/Udp),ITcpServerAgent、IUdpServerAgent
(2)可将异步的消息请求/回复转化为同步的方法调用。 

  ESFramework 主要支持基于TcpUdpC/S 系 统,所以客户端和服务端之间是通过消息进行交互的。如果仅仅是客户端发出请求、服务器给出服务这种情况很容易处理,但是如果服务端有主动发消息给客户端的 情况,事情就会变得稍微复杂。通常,客户端会有一个专门的接收线程来负责从网络接收数据,然后把接收的消息交给对应的处理器处理,或者,这个接收到的消息 是个服务端给出的回复,那么这个回复就应该交给发出请求的请求者,但是对应的请求者在哪里了?这种回复消息与请求消息的匹配是比较繁琐的,特别是在上述服 务端可以主动给客户端发送消息的情况下。为了简化这个过程,IServerAgent 出现了,它用于客户端,像它的名字一样,可以把它当作服务器。IServerAgent 的主要目的就是将消息请求/ 回复转换成方法调用,就像该接口定义的一样:

 

 

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

    
public   enum  DataPriority
    {
        High ,
// 紧急命令
        Common , // 如普通消息,如聊天消息
        Low , // 如文件传输
        CanBeDiscarded  // 如视频数据、音频数据
    }

 

首先解释一下参数dataPriority 的意义,dataPriority 参数仅仅对Tcp 协议起作用,当有多个请求要同时发送时,它决定了发送的优先级。CanBeDiscarded 表明这个消息在网络繁忙时可以被抛弃,比如即时通讯的音频数据、视频数据等。关于这个数据发送的优先级机制的实现是ITcpAutoSender ,这个组件会在后文中介绍。

    CommitRequest 方法提交 一个请求消息该给服务器,并返回一个回复消息给请求者。这就是一个方法调用!!!其间隐藏了通过网络将消息发送给服务器并从服务器获取结果的中间细节。这 是怎么做到的?思路其实很简单,只是描述起来有些复杂。主要要解决两个问题,一是如何将请求消息与对应的回复匹配起来,二是CommitRequest 从哪里找到匹配的回复。
    对于第一个问题,相信大家还记得IMessageHeader 定义中有个CorrelationID 属性,正如其名,这是一个随机数,每生成一个新的请求消息,就会产生一个随机数赋值给CorrelationID 属性,由于随机数重复的可能性很小,所以可以把它当作是唯一的。这样一个随机数就唯一的标志了一个请求,当服务端收到这个请求后,就处理这个请求,并把回复消息的消息头中的CorrelationID 属性设为与对应的请求消息的CorrelationID 一样的值,这样,客户端收到回复消息后,就可以和对应的请求消息一一对应起来了。

  对于第二个问题的解释,就需要涉及到ESFramework 中支持客户端开发的其它两个组件:EsbPassiveDataDealerIResponseManagerEsbPassiveDataDealer 是客户端用户处理所有接收到的消息的处理器,而IResponseManager 组件用于暂存所有的来自服务端的回复。对于每个接收到的消息,EsbPassiveDataDealer 判断其是否为回复,如果是,则将其交给IResponseManager 暂存。IResponseManager 为暂存的每个回复都设置的生存期TTL ,如果回复在IResponseManager 中的时间超过了这个TTL ,则会被删除。

  你也许已经想到第二个问题的解决方法了。是的,CommitRequest 方法将请求发送到网络之后,就定时从IResponseManager 中寻找CorrelationID 为请求消息头的CorrelationID 值的回复消息,如果找到,就返回它,否则就等待循环,直至超时抛出TimeoutException 异常。下面给出IResponseManager 的接口定义:
   

    public   interface  IResponseManager
    {
        
void  Initialize() ;

        
void  PushResponse(NetMessage response) ;
        NetMessage PopRespose(
int  correlationID , int  serviceKey) ;   // 立即返回
        NetMessage PickupResponse( int  serviceKey , int  corelationID) ; // 在TimeoutSec时间内不断的PopRespose

        
///   <summary>
        
///  ResponseTTL 如果一个回复在管理器中存在的时间超过ResponseTTL,则会被删除。如果ResponseTTL为0,则表示不进行生存期管理
        
///   </summary>         
         int  ResponseTTL{ set  ;}  // s

        
///   <summary>
        
///  如果在TimeoutSec内,仍然接收不到期望的回复,则抛出异常。取0时,表示不设置超时
        
///   </summary>
         int  TimeoutSec{ set  ; }     
    }

       IServerAgent的具体实现包括TcpServerAgent和UdpServerAgent,分别支持Tcp协议和Udp协议的客户端开发。从它们的接口定义中可以看到它们都借助于IServerAgentHelper实现自己。

    public   interface  IServerAgentHelper
    {
        IEsbLogger          EsbLogger{
set  ;  get  ;}
        IContractHelper   ContractHelper{
set  ;  get  ;}
        INetMessageHook   NetMessageHook {
set  ;  get  ;}
        IPassiveHelper    PassiveHelper {
set  ;  get  ;}

        IResponseManager  ResponseManager{
set  ; get  ;}    

        ISingleMessageDealer SingleMessageDealer{
set  ;  get  ;}        

        IMessageDispatcher ConstructDispatcher () ;        
    }

    我们要特别注意其ConstructDispatcher方法,该方法构建了一个客户端比较常用的消息分配器实例。在介绍IMessageDispatcher 时,我们讲过,客户端通常不需要对消息Spy,仅仅需要Hook就可以了,所以IServerAgentHelper正是通过对各组件的组装做到了这一点:

        public  IMessageDispatcher ConstructDispatcher()
        {
            
// NakeDispatcher
            EsbPassiveDataDealer dealer      =   new  EsbPassiveDataDealer( this .responseManager , this .passiveHelper , this .singleMessageDealer) ;
            EsbPassiveDealerFactory factory 
=   new  EsbPassiveDealerFactory(dealer) ;
            NakeDispatcher nakeDispatcher   
=   new  NakeDispatcher() ;
            nakeDispatcher.ContractHelper   
=   this .contractHelper ;
            nakeDispatcher.DataDealerFactory
=  factory ;

            
// MessageDispatcher
            IMessageDispatcher messageDispatcher  =   new  MessageDispatcher() ;
            messageDispatcher.ContractHelper     
=   this .contractHelper ;
            messageDispatcher.NetMessageHook     
=   this .netMessageHook ;
            messageDispatcher.NakeDispatcher     
=  nakeDispatcher ;

            
return  messageDispatcher ;
        }

    在IServerAgent的基础之上,我们就可以从一个新的角度来设计客户端的结构的,那就是采用和功能服务器一样的插件方式。在ESFramework的支持下,我们的应用开发变得非常简洁和简单,所要做的主要内容就是开发服务端的“业务功能插件”和对应的客户端的“PassiveAddin”(客户端插件)。 如 果我们的应用已经发布投入使用,而此时用户要求添加一项新的业务,那将是非常简单的事情,那就是开发一个实现了新业务的功能插件动态加载到功能服务器中、 再开发一个对应的客户端插件动态加载到客户端中,这样就可以了。服务器不用重编译、甚至不用停止服务;客户端也不用重编译、甚至不用停止使用。一切都是在 运行中动态完成的。

分享到:
评论

相关推荐

    C#实现Socket异步通信完整封装库源码

    总的来说,C#实现的Socket异步通信封装库源码为开发者提供了一套完整的网络通信解决方案,涵盖了服务器监听、客户端连接、服务抽象以及异步操作的管理。这种封装使得开发者能够更加专注于业务逻辑,而不用过于关心...

    VCTcp异步Socket通信类

    异步Socket通信是一种非阻塞的通信方式,它允许应用程序在等待数据传输的同时执行其他任务,提高了程序的响应性和效率。在Windows平台上,这通常通过Windows套接字API(Winsock)中的异步方法实现,如WSAAsyncSelect...

    winformSocket异步通信

    异步Socket通信在WinForm中的实现主要依赖于.NET Framework提供的Asynchronous Client Socket。这种方式允许UI线程不被阻塞,提高用户体验。关键步骤包括: 1. **创建Socket对象**:使用`new Socket(AddressFamily....

    Socket异步通信封装

    `Wodsoft.Net.Sockets.dll`和`Wodsoft.Net.Sockets.XML`这两个文件可能是第三方库,其中`Wodsoft.Net.Sockets.dll`是包含异步Socket通信实现的动态链接库,而`Wodsoft.Net.Sockets.XML`可能是该库的XML文档,提供了...

    Android TCP Socket通信封装

    在Android开发中,TCP Socket通信是移动应用与服务器进行数据交互的一种常见方式。TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,确保了数据的顺序传输和数据完整性...

    socket在msdn上同步及异步示例

    2. **异步Socket操作**: 异步操作适合长时间运行或者需要处理多个并发连接的情况。异步操作通常涉及`BeginXXX`和`EndXXX`方法对,如`BeginConnect`、`EndConnect`,`BeginReceive`、`EndReceive`等。在调用`...

    基于异步IO的socket通信程序

    在实际编程中,异步socket通信需要考虑的问题还包括错误处理、性能优化、并发控制等。例如,通过设置合理的缓冲区大小,可以提高数据传输效率;使用线程池管理客户端请求,防止过多的并发导致资源耗尽;以及使用非...

    C#Socket通信稳定完整版类库实例

    本实例,"C# Socket通信稳定完整版类库实例",为我们提供了一个全面且稳定的解决方案,用于实现客户端与服务器之间的数据交互。下面我们将深入探讨C#中的Socket通信及其相关知识点。 1. **Socket基础** Socket,又...

    QT socket tcp异步通信

    基于QThread和QTcpScoket进行异步通行封装。

    关于socket的基于TCP协议的异步通信系统--TongXing.DLL

    最近做了一个关于socket的基于TCP协议的异步通信系统--TongXing.DLL;它里面封装了通信的一些比较复杂的方法:1:数据加密解密 2:数据失败自动重发 3:心跳模块 4:客户端网络问题断开自动重连 5:服务器自动拒绝...

    C#写的Socket通信组件 封装了底层Socket通信

    Socket通信在IT行业中是网络编程的基础,特别是在C#这样的.NET框架下,Socket通信组件的封装对于简化开发工作、提高代码可复用性至关重要。本文将详细介绍C#中的Socket通信以及如何进行封装,以便开发者能够更好地...

    C# Socket异步通信+事件与委托+通信程序与界面分离

    为了实现通信程序与界面的分离,我们需要将网络通信的逻辑封装在一个单独的类(如"NetworkManager")中,该类负责处理所有的Socket操作和事件发布。UI组件只需关注事件处理,而不关心底层通信的细节。这样的设计遵循...

    C#通讯 Socket异步编程源代码与资料

    首先,Socket是网络通信的基石,它提供了一种进程间通信(IPC)的方式,允许两个应用程序通过网络进行数据交换。在C#中,System.Net命名空间下的Socket类为我们提供了实现Socket通信的接口。异步Socket编程则是在这...

    MFC编程实现socket通信

    为了提高代码的可读性和复用性,可以将Socket通信的相关操作封装到一个专门的类中,如CSocketServer或CSocketClient。这样,当需要进行Socket通信时,只需实例化对应的类并调用其方法即可。 总结来说,MFC编程实现...

    Socket通信经典源码HPSocketCS

    Socket通信在IT行业中扮演着至关重要的角色,它是网络应用程序间通信的基础。HPSocketCS是一个专为.NET平台设计的高效、稳定的Socket通信框架,适用于开发跨平台的客户端和服务器端应用。本文将深入探讨HPSocketCS的...

    使用IOCP完成端口和SOCKET封装的成熟异步TCP类

    使用IOCP完成端口和SOCKET封装的异步TCP类。 支持客户端和服务器的常用TCP接口:绑定Bind、监听Listen、接收Recv、连接Conn、发送Send、关闭Close。所有接口均使用异步回调的方式处理,内部实现使用Windows下性能...

    C# Socket 客户端服务端封装带使用实例

    Socket编程在IT行业中是网络通信的基础,特别是在C#这样的编程语言中,...以上就是关于"C# Socket客户端服务端封装带使用实例"的知识点,通过理解并实践这些内容,开发者可以更加高效地构建基于C#的网络通信应用。

    通用TCP/UDP异步SOCKET通讯封装及Demo

    本教程重点讨论的是如何进行通用的TCP/UDP异步SOCKET通讯的封装,并提供服务端与客户端的示例应用。 首先,TCP是一种面向连接的、可靠的传输协议,它确保了数据包的顺序传输和错误检查,适用于对数据完整性要求较高...

    MFC Socket通信协议实现

    为了实现异步Socket通信,我们需要使用CAsyncSocket类,它提供了非阻塞模式,允许在等待数据传输的同时执行其他任务。 以下是一些关键步骤来实现MFC Socket通信协议: 1. **初始化Winsock**:在开始任何Socket操作...

    socket异步通信框架

    1、封装消息的发送和接收方法,支持不同数据类型、业务类型的消息 2、具体业务客户端和服务器实现类,继承以下三个事件方法就可以处理具体业务 Protected Overrides Sub OnEndReceiveEvent(ByVal handler As Socket...

Global site tag (gtag.js) - Google Analytics