• 可靠通信的保障 —— 使用ACK机制发送自定义信息——ESFramework 通信框架4.0 快速上手(12)


    使用ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter接口的Send方法,我们已经可以给服务端或其它在线客户端发送自定义信息了,那么,如何得知接收方是否已经收到了我们发出的信息了呢?特别是针对一些非常重要的信息,确认对方已经收到是非常重要的。ICustomizeInfoOutter接口增加了SendCertainly方法来解决这个问题。

    一.启用ACK机制

          ACK,即确认的意思。当我们发送一个自定义信息给对方时,对方收到信息后,回复一个ACK给我们,我们接收到了ACK,就知道对方一定收到信息了。

         

          ICustomizeInfoOutter接口的SendCertainly方法就是启用了带ACK机制的发送:

    复制代码
            /// <summary>
            /// 向服务器发送二进制信息,并等待服务器的ACK。当前调用线程会一直阻塞,直到收到ACK;如果超时都没有收到ACK,则将抛出Timeout异常。
            /// </summary>
            /// <param name="informationType">自定义信息类型</param>
            /// <param name="info">二进制信息</param>
            void SendCertainly(int informationType, byte[] info);

            /// <summary>
            /// 向在线用户targetUserID发送二进制信息,并等待其ACK。当前调用线程会一直阻塞,直到收到ACK;如果超时都没有收到ACK,则将抛出Timeout异常。
            /// </summary>
            /// <param name="targetUserID">接收消息的目标用户ID</param>
            /// <param name="informationType">自定义信息类型</param>
            /// <param name="info">二进制信息</param>      
            void SendCertainly(string targetUserID, int informationType, byte[] info);
    复制代码

          同样的,服务端ICustomizeInfoController接口的SendCertainly方法,也是启用了带ACK机制的发送:

    复制代码
            /// <summary>
            /// 向ID为userID的在线用户发送二进制信息,并等待其ACK。当前调用线程会一直阻塞,直到收到ACK;如果超时都没有收到ACK,则将抛出Timeout异常。
            /// </summary>
            /// <param name="userID">接收消息的用户ID</param>
            /// <param name="informationType">自定义信息类型</param>
            /// <param name="info">二进制信息</param>          
            void SendCertainly(string userID, int informationType, byte[] info);
    复制代码

    (1)无论是客户端发送信息给服务端、还是客户端发送信息给其它客户端、或者是服务端发送信息给客户端,它们采用的ACK机制的原理是一样的。

    (2)当框架接收到需要ACK的信息时,会自动回复ACK给发送方。这是由ESPlus底层自动完成的,应用程序不需要关心。

    (3)ESPlus会先回复ACK,然后才会调用处理信息的方法。所以,当发送方接收到ACK回复时,只是意味着接收方已经接收到了信息,并不表示接收方已经处理完了信息。

    (4)如果接收方在规定的时间内(默认为30秒)都没有收到ACK,则会抛出超时的异常。当然,在规定的时间内没有收到ACK,并不一定就是接收方没有收到信息,而是有几种可能性:

           a.由于网络慢,导致ACK延迟抵达发送方。

           b.接收方已经掉线。

           c.发送方已经掉线。

    (5)SendCertainly方法采用的是阻塞模型,即只有收到ACK后才会返回,否则一直阻塞当前调用线程。如果既需要ACK机制的发送,又不希望阻塞当前线程,那么,可以异步调用SendCertainly方法,并通过回调获知是否有超时异常。

    (6)ESPlus.Application.CustomizeInfo命名空间下的主要接口的方法已经比较多了,我们这里厘清一下。比如,客户端由ICustomizeInfoOutter接口发出的CommitRequest调用将被服务端ICustomizeInfoBusinessHandler接口的HandleRequest方法来处理,下图我们通过箭头将这些调用与处理关联起来:

          

    二.具有同样效果的同步调用

          使用自定义信息,我们还有几个同步调用的方法,比如ICustomizeInfoOutter接口的CommitRequest方法和CommitP2PRequest方法、以及ICustomizeInfoController接口的QueryClient方法,这些同步调用的方法都是有返回值的,如果超时没有收到返回的信息,也抛出超时异常。

          同步调用与带ACK机制的发送采用的是完全相同的模型,我们完全可以使用同步调用来模拟ACK机制,比如,需要确认的信息就使用同步调用发送,接收方在处理同步调用的时候直接返回null,就可以达到同样的效果。

           同步调用与带ACK机制的发送有两点小区别:

    (1)在同步调用中,接收方回复的是对应请求的答案;在带ACK机制的发送中,接收方回复的是ACK。

    (2)在同步调用中,接收方是处理完信息后才回复;在带ACK机制的发送中,接收方则是先回复ACK,再处理收到信息。

          由于同步调用和带ACK机制的发送都有可能超时抛出异常,所以,我们在程序中应当将其try...catch起来,以防止应用程序抛出未被截获的异常。 

     三.在消息骨架流程中挂接ACK机制

          如果不使用Rapid引擎,而自己来组装消息处理流程,我们就可以直接在消息骨架流程上,挂接一个自定义的IMessageSpy,来自动回复那些需要ACK的消息。并且,这种方式的优势在于,我们可以对任意类型的消息采用ACK机制,而本文介绍的SendCertainly方法只是针对自定义信息启用ACK机制。当然,对于Rapid引擎的使用者来说,用得最多的也就是自定义信息,所以,也应该足够了。(关于如何让协议类序列化达到最高性能且得到最精简的自定义信息,请参见ESFramework通信框架通信框架 4.0 快速上手(11) -- 使用紧凑的序列化器,数倍提升性能 )

  • 相关阅读:
    第二十九课 循环链表的实现
    第二十八课 再论智能指针(下)
    第二十七课 再论智能指针(上)
    第二十六课 典型问题分析(Bugfix)
    普通new和placement new的重载
    leetcode 581. Shortest Unsorted Continuous Subarray
    leetcode 605. Can Place Flowers
    leetcode 219. Contains Duplicate II
    leetcode 283. Move Zeroes
    leetcode 217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/sylone/p/6096987.html
Copyright © 2020-2023  润新知