【ZProRx 重装上阵】 第四回 网络

9 篇文章 1 订阅
7 篇文章 0 订阅

Net 网络

ZProRx 包括Socket 和Http的封装支持。

Socket

使用Topic进行消息的发送与订阅,分为客户端与Server端两种情况。 数据包使用的共通的NetPackage结构,其模板使用可以用于扩展支持自定义的数据。

    public class NetPackage<T, TErrorEnum> // where TErrorEnum : System.Enum
    {
        private ZProperty<T> data = new ZProperty<T>();
        private ZProperty<TErrorEnum> status = new ZProperty<TErrorEnum>();
        private ZProperty<string> msg = new ZProperty<string>();

        private Dictionary<string, string> headers = new Dictionary<string, string>();
    }

Demo如下:

    var propObser = ZPropertySocket.ReceivePackage<TestPropData>("topic/multisubscribe");

    propObser.Subscribe(str =>
    {
        //... do something
    }).AddTo(disposables);

    ZPropertySocket.PostPackage<TestPropData>("topic/multisubscribe", data).Subscribe();

注意: 客户端订阅一个消息时,会加上ClientId为Topic的一部分。 从Socket层来说,其ClientId是透明的。需要应用进行封装与控制。

接口格式如下:

  1. 发送消息 Post[Package] 用于异步发送,支持错误返回,即发送失败。比如网络异常等。其返回值不表示接收者已经接收。 Send[Package] 用于同步发送,并接收返回值。

  2. 接收消息 Receive[Raw/Package/RawPackage(SocketPackageHub)/LowSocketPackage][AndResponse]

消息类型如下:

  • Raw 发送普通字符串
  • Package 是ZP格式的数据包,格式如下,如果其支持Response时,内部是使用串行返回的。
  • PackageAndResponse 表示接收到之后可以进行返回。返回值支持ZNull,其不会占用传输的Size,但其表达接收到返回值,常常用于回应。
  • RawPackage 即接收SocketPackage包,是指带有ClientID的Package包。如果其支持Response,那么内部是使用的并行返回的。
  • RawPackageAndResponse 接收端可以获取到SocketPackageHub 其包括ISocketPackage 原始数据包,和封装的NetPackage包,可以获取额外的客户端内容。比如ClientId等。
    public interface ISocketPackage
    {
        string Key { get; }
        string Value { get; set; }
        string Topic { get; }
    }
  • LowSocketPackage 以接口的返回 ISocketPackage包,用户可以根据需求自己进行Package的解析,当然与需要发送端协商一致。 这里要注意与上面的RawPackage 和 RawPackageAndResponse 返回的是不同的,即返回的直接的 ISocketPackage包,需要自行进行数据包的解析。

SocketObservable

以上可以看到ZProRX 对于Socket的处理也是反映式的。

其中使用的核心类如下(对于调用者是透明的) Socket[RawRequest/Request/Package/RawPackage(SocketPackage)]Observable

  • Request 用于通用的请求
  • Package 用于Receive请求

返回IObservable,其好处是,支持取消功能,调用Dispose方法会进行反注册等取消操作。 支持Retry/Delay等Operator 相关的操作

T 参数

支持接收Package的API,都对应的四套模板用于处理不同的参数形式(接收以及返回的数据格式),基本包括:

  •  其中无参数的即以IRawDataRef去接收数值,返回IObservable,应用根据 GetData方法获取到对应的数据。
    (IRawDataPref rawData, ISocketPackage rawPack) => {
        Assert.IsTrue(string.Compare(rawPack.Key, "1000") == 0);

        //throw new Exception(""); 
        //throw new ZNetMultiException<TestErrorEnum>(TestErrorEnum.Error1);

        //get data from IRawDataRef
        var data = rawData.GetData<TestPropData>();
        Assert.IsTrue(string.Compare(data.name.Value, "testobjectname") == 0);

        //return result
        return true;
    });
  • <T, TResult>
  • <T, TError,TResult>

以上不同的层次,可以进一步明确接收参数、回应返回值参数、回应可能出现的错误 <T, TResult> 时对应可能的错误值为 ZNetErrorEnum

<T, TError,TResult> 时,错误值为自定义参数类型,通过[MultiEnum] 方法对ZNetErrorEnum进行兼容。

注意 对于无参数的方式,其优点是有很强的通用性,但是以牺牲是一定的性能(需要转换多次)以及可读性。 对于明确返回值类型以及错误类型的还是推荐使用对应的模板参数。

SendPackage的API要简化许多,这里只有<T, TResult> 和<T, TError,TResult>两个版本。 对于没有明确返回错误模板参数的,在处理中返回自定义错误也是可以的,这时要使用 SendPackage2<T, TResult> 进行接收返回值,其可以接收所有异常,其异常类型为ZNetException。 SendPackage<T, TResult>其只能接收并抛出 ZNetErrorEnum 异常值,如果Server端返回其它异常,Server端会直接抛出,而Client端无法接收到返回值了。 当然SendPackage2<T, TResult>也同样是有一定的性能损耗。

    //test for common TError
    disp = ZPropertySocket.ReceivePackageAndResponse<TestPropData, bool>("topic/responseCustomError", null).
        Subscribe(             //< TestPropData, bool> support return 
        (TestPropData a1) => {
            Assert.IsTrue(string.Compare(a1.name.Value, "testobjectname") == 0);

            //throw new Exception(""); 
            throw new ZNetMultiException<TestErrorEnum>(TestErrorEnum.Error1);

            return true;
        }).AddTo(disposables);

    ZPropertySocket.SendPackage2<TestPropData, bool>("topic/responseCustomError", data)
    .Subscribe(bRet =>
    {
        taskEnd.Value = true;
        //Assert.IsTrue(bRet);
    }, error =>
    {
        //Assert.IsTrue((error as ZNetException<ZNetErrorEnum>).Error == ZNetErrorEnum.ActionError);
        Assert.IsTrue(error.IsMultiError<TestErrorEnum>(TestErrorEnum.Error1));
        taskEnd.Value = true;
    });

TestErrorEnum 为自定义的枚举错误类型。

推荐使用ZException进行统一接收以及Rx的Catch操作。以下是Ignore一个异常。

    .CatchIgnore((ZException ex) =>
    {
        Assert.IsTrue(ex.IsMultiError<TestErrorEnum>(TestErrorEnum.Error1));
        Assert.IsTrue(true);

        taskEnd.Value = true;
    })    

以下是Catch一个异常并返回新的数据流。其实是新建立了一个分支。

    .Catch<bool, ZException>((e) => {
        return Observable.Return(true);
    })

安全

在TTPServer端 ValidatingMqttClients的方法中进行相关的安全Token验证。Token来至ZRoom的Token (在调用 JoinRoom API返回) /api/v1/matrix/arch/users/{vroomid} [TODO] 目前未对应

Retry支持

Rx规范对应,Net API Retry的支持,要支持Retry,其内部原理是实现进行重新订阅,需要支持Retry的Observable的实际动作应该在SubscribeCore 方法中完成。

Receive API 不支持Retry

Reactive

以下都是ZRropertySocket.Socket/Net Receive[Raw/Package/RawPackage(SocketPackage)/LowRawPackage][AndResponse]

如下所示:对于Receive Package 支持的反映式的处理方法。

主要的订阅包括:

IObservable<SocketPackageHub<T>>
IRawPackageObservable<IRawDataPref>
IRawPackageObservable<T, TError>
IRawPackageObservable<T>

RawPackage 的支持

包括的订阅:

IObservable<SocketPackageHub<T>>
IRawPackageObservable<IRawDataPref>
IRawPackageObservable<T, TError>
IRawPackageObservable<T>

Dispose

  • 对于Receive操作一般要保持长时间的Active状态,所以一般是Channel/Room/APP退出时进行调用,可以与对应的Extension进行关联
  • 对于Send/Post 操作,一般是短时间进行,可以不进行Dispose。但对于些有返回值的Send操作,需要可以进行Dispose操作。其实内部在接收返回值时,会定义一个Result的临时的Topic进行接收。这个是会自动在接收到消息之后进行反注册的。但推荐还是进行Dispose操作,使用using。

Web Request Support

  • 对于Recevie + [AndResponse]的接收API, 其返回值类型还支持错误值处理,即通过Server端返回错误值,目前支持ZNetErrorEnum通用Enum类型,同时支持自定义的Enum类型。这里使用的复合Enum类实现,MultiEnum<ZNetErrorEnum, TErrorEnum> 如果Recevie 端(Server)需要返回给错误信息给调用者,通过Throw ZNetException类的异常。

如下参考的错误定义,Base从ZNetErrorEnum.MaxError开始定义。

public enum RoomErrorEnum 
{
    BaseError = ZNetErrorEnum.MaxError + 0x100,
    UnsupportedUnit,
    NotFindUnit,
    NotFindRoom,
    NotInService,
}

主要用法是

[TODO] 错误码要与HTTP 标准码进行关联,目前还未设计

注意事项

对网络等返回Observable的API是不支await的,因为接收到个消息后,不会触发Completed事件。 如: ZPropertyNet.Post/Get/Put

如果一定直接使用它们,并需要进行Await的话,需要调用Fetch操作。 对于整体ZPropertySocket 的API也都是同样的问题。 类似的还有一些带有连续的消息,也都只有Completed时才能Await返回。

 

相关链接:

项目开源地址:https://github.com/bennychao/ZProRx.Lib

下载安装:(ZP.Lib.Server 是ZRroRx的核心库,后续其它功能库陆续开放中)

  • .Net CLI >dotnet add package ZP.Lib.Server --version 1.0.3
  • 或 VS 2019 Nuget 包管理中搜索"ZP.Lib.Server"并安装(推荐)

ZProRx.Lib Unity Package 1.0.3 (用于在Untiy中使用)下载地址: 

https://github.com/bennychao/ZProRx.Lib/releases/ 

https://github.com/bennychao/ZProRx.Lib/Publish/ZProRx.Lib.package

 

下一节

【ZProRx 重装上阵】 第三回 绑定

【预告】【ZProRx 重装上阵】 第五回 反映式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值