
Channel意为“通道”,在RRQM中,Channel是基于TCP协议的数据传输通道。一个TCP信道可以创建很多Channel,每个Channel之间数据互不影响,彼此独立。
1.2 架构是怎么样的?性能如何?Channel的架构比较简单,基本的逻辑就是,用一个int类型的数值标识为Channel的ID,每次在发送数据时,携带ID即可知晓该数据发往哪个通道。
性能和TCP相比,假如使用NormalDataHandlingAdapter适配器,则相当于把发送的数据再复制一份。假如使用FixedHeaderDataHandlingAdapter适配器(所有支持CanSplicingSend的适配器),则几乎没有区别(此处有疑惑的小伙伴请看:数据处理适配器相关)。
在学习本节之前,您必须熟悉RRQM中的Protocol服务器与客户端(或其派生类,例如文件传输和RPC)的创建,如果您不熟悉,请在下列链接中了解。
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