【RRQMSocket】C#基于TCP、自定义协议Channel持续传输大数据

文章目录

    • 一、概述
        • 1.1 什么是Channel?
        • 1.2 架构是怎么样的?性能如何?
        • 1.3 本节须知
    • 二、程序集源码、Demo下载
        • 2.1 源码位置
        • 2.2 Demo位置
    • 三、安装
    • 四、创建Channel
    • 五、订阅Channel
    • 六、注意事项


一、概述

1.1 什么是Channel?

Channel意为“通道”,在RRQM中,Channel是基于TCP协议的数据传输通道。一个TCP信道可以创建很多Channel,每个Channel之间数据互不影响,彼此独立。

1.2 架构是怎么样的?性能如何?

Channel的架构比较简单,基本的逻辑就是,用一个int类型的数值标识为Channel的ID,每次在发送数据时,携带ID即可知晓该数据发往哪个通道。

性能和TCP相比,假如使用NormalDataHandlingAdapter适配器,则相当于把发送的数据再复制一份。假如使用FixedHeaderDataHandlingAdapter适配器(所有支持CanSplicingSend的适配器),则几乎没有区别(此处有疑惑的小伙伴请看:数据处理适配器相关)。
【RRQMSocket】C#基于TCP、自定义协议Channel持续传输大数据_第1张图片

1.3 本节须知

在学习本节之前,您必须熟悉RRQM中的Protocol服务器与客户端(或其派生类,例如文件传输和RPC)的创建,如果您不熟悉,请在下列链接中了解。

  • 【RRQMSocket】C#搭建TCP自定义协议、Protocol服务器和客户端

二、程序集源码、Demo下载

2.1 源码位置

RRQMSocket

2.2 Demo位置

RRQMBox

三、安装

安装RRQMSocket即可,具体步骤详看链接博客。

VS、Unity安装和使用Nuget包

四、创建Channel

在Channel使用之前,必须先创建。

Channel的创建必须由IProtocolClient的实现类执行(客户端实现为ProtocolClient,服务器实现为ProtocolSocketClient)。

调用CreateChannel的(重载)函数进行创建,创建完成后,通道可读可写(可以同时发送和接收),下列代码仅演示读取。

代码示例如下:

Channel channel = client.CreateChannel(10);//创建指定ID的通道。

//Channel channel = client.CreateChannel();//创建ID随机的通道。
Console.WriteLine($"成功创建通道,请使用{
       channel.ID}订阅");

while (channel.MoveNext())//线程阻塞接收,直至接收完成或错误
{
     
    byte[] data = channel.GetCurrent();//获取当前数据对象,此操作相当于把ByteBlock进行ToArray
    Console.WriteLine($"已收到数据,长度为:{
       data.Length}");

    //下列注释内容为高效处理数据,省略了ByteBlock进行ToArray的操作。

    或者直接获取内存块
    //ByteBlock byteBlock = channel.GetCurrentByteBlock();

    //byteBlock.Pos = 6;//先预设流位置为6
    //if (byteBlock.TryReadBytesPackageInfo(out int pos,out int length))//获取数据包信息
    //{
     

    真实数据则是从byteBlock.Buffer的pos,长度为length
    //Console.WriteLine($"已收到数据,长度为:{length}");
    //}

    //byteBlock.SetHolding(false);//必须手动释放!!!不然内存池会一直创建,性能大大折扣。
}

//代码执行到此处时,意味着通道接收已结束,可通过channel.Status获取最后的状态。
Console.WriteLine($"已结束接收,状态为{
       channel.Status}");

五、订阅Channel

订阅方必须知晓创建方已经创建成功的Channel的ID。然后调用TrySubscribeChannel函数订阅,成功后也会获得一个Channel ,同样可读可写

最后双方可通过Channel 进行双向读写。

 //必须知道接收方已创建通道的ID
 if (protocolClient.TrySubscribeChannel(id, out Channel channel))
 {
     
     byte[] data = new byte[1024*1024];
     for (int i = 0; i < 10; i++)
     {
     
         channel.Write(data);//持续写入(发送)
     }
     channel.Complete();//最后调用完成
     //channel.Cancel();//或调用取消
     //channel.Dispose();//或销毁
     Console.WriteLine("发送完成");
 }
 else
 {
     
     Console.WriteLine("未找到该ID对应的Channel");
 }

六、注意事项

Channel 的接收是同步的,如果发送方发送速度较快,接收方速度太慢的话,会导致Channel缓存队列已满,从而拥塞TCP信道。应当尽量避免这种情况发生。

Channel缓存队列容量可直接设置其静态属性CacheCapacity

你可能感兴趣的