跳到主要内容
版本:3.0

路由包传输

定义

命名空间:TouchSocket.Dmtp
程序集:TouchSocketPro.Dmtp.dll

一、说明

路由包传输模式是,手动版的Rpc,能够实现发送、然后同步等待响应式的通讯。但是与Rpc区别的是,路由包是自己把握数据序列化,可以完全使用内存池。极大的降低内存消耗。

包模式的应用场景,就是中小型二进制数据的传输。例如:传输100张照片,每张大约5Mb的。

用协议直接Send,怕对方没正确处理保存。没法拿到处理回执。

用Rpc,发送得序列化,解析得反序列化,而且5Mb数据也用不了内存池。内存会抖动的厉害。

用Rpc+Channel,又显得麻烦。

所以用路由包传输模式。高效,简单。

二、使用

路由包传输模式是由DmtpRouterPackageFeature功能插件提供的,所以需要添加UseDmtpRouterPackage

.ConfigurePlugins(a =>
{
a.UseDmtpRouterPackage();//添加路由包功能插件
})

其次,要完成路由包传输,就得自己定义请求包和响应包。此处简单定义两个包用于测试。具体关于包的打包、解包详细操作可以看包序列化

/// <summary>
/// 定义请求包
/// </summary>
class MyRequestPackage : DmtpRouterPackage
{
/// <summary>
/// 包尺寸大小。此值并非需要精准数值,只需要估计数据即可。其作用为申请内存池。所以数据应当大小合适。
/// </summary>
public override int PackageSize => 1024 * 1024;

/// <summary>
/// 自定义一个内存属性。
/// </summary>
public ByteBlock ByteBlock { get; set; }

public override void PackageBody(ByteBlock byteBlock)
{
base.PackageBody(byteBlock);
byteBlock.WriteByteBlock(this.ByteBlock);
}

public override void UnpackageBody(ByteBlock byteBlock)
{
base.UnpackageBody(byteBlock);
this.ByteBlock = byteBlock.ReadByteBlock();
}
}

/// <summary>
/// 定义响应包
/// </summary>
class MyResponsePackage : DmtpRouterPackage
{
/// <summary>
/// 包尺寸大小。此值并非需要精准数值,只需要估计数据即可。其作用为申请内存池。所以数据应当大小合适。
/// </summary>
public override int PackageSize => 1024;
}

【请求端】

using (ByteBlock byteBlock = new ByteBlock(1024*512))
{
byteBlock.SetLength(byteBlock.Capacity);//此处模拟一个大数据块
MyRequestPackage requestPackage = new MyRequestPackage()
{
ByteBlock = byteBlock,
Metadata = new Metadata() { { "a", "a" } }
};
var response = client.GetDmtpRouterPackageActor().Request<MyResponsePackage>(requestPackage);

//client.Logger.Info(response.Message);
}

【响应端】

响应端除了UseDmtpRouterPackage之外,还需要添加一个插件,实现IDmtpRouterPackagePlugin功能,主要在里面实现响应的动作。

class MyPlugin : PluginBase, IDmtpRouterPackagePlugin
{
private readonly ILog m_logger;

public MyPlugin(ILog logger)
{
this.m_logger = logger;
}
public async Task OnReceivedRouterPackage(IDmtpActorObject client, RouterPackageEventArgs e)
{
//m_logger.Info($"收到包请求");
await e.ResponseAsync(new MyResponsePackage()
{
Message = "Success"
});
//m_logger.Info($"已响应包请求");

//一般在当前插件无法处理时调用下一插件。此处则不应该调用
//await e.InvokeNext();
}
}

本文示例Demo