路由包传输
定义
命名空间: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();
}
}