跳到主要内容
版本:3.0

b.远程流映射

定义

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

一、说明

可以在通信对方,创建一个Stream,然后映射到本地,由本地直接进行读、写等操作。

二、场景

当远程主机拥有一个超大流数据(可能是文件,或者其他)时,本地只想访问其部分数据的话,就可以使用该功能。 例如,假设C服务器有个10Gb的文件。A客户端需要其10000-20000字节之间的数据,那你此时可以使用该功能,直接进行读取。

三、使用

该功能由DmtpRemoteStreamFeature功能插件提供。所以需要客户端服务器都需要UseDmtpRemoteStream

.ConfigurePlugins(a =>
{
a.UseDmtpRemoteStream();
});

【请求端】 任意Dmtp终端均可以调用LoadRemoteStream创建一个流数据映射。 同时可以传递一个元数据组。用于载入自定义消息。

var metadata = new Metadata();
metadata.Add("tag", "tag1");

var remoteStream = client.GetDmtpRemoteStreamActor().LoadRemoteStream(metadata);

【响应端】 响应端定义一个插件,实现IDmtpRemoteStreamPlugin,然后实现需要载入的具体流信息。示例中是以MemoryStream作为流主体。

internal class MyRemoteStreamPlugin : PluginBase, IDmtpRemoteStreamPlugin<ITcpDmtpSessionClient>
{
public async Task OnLoadingStream(ITcpDmtpSessionClient client, LoadingStreamEventArgs e)
{
if (e.Metadata["tag"] == "tag1")
{
e.IsPermitOperation = true;//需要允许操作

client.Logger.Info("开始载入流");
//当请求方请求映射流的时候,会触发此方法。
using (var stream = new MemoryStream())
{
await e.WaitingLoadStreamAsync(stream, TimeSpan.FromSeconds(60));

client.Logger.Info($"载入的流已被释放,流中信息:{Encoding.UTF8.GetString(stream.ToArray())}");
}

return;
}

//如果不满足,调用下一个插件
await e.InvokeNext();
}
}

四、读写

当RemoteStream被成功创建以后,即可直接Read、Write。因为RemoteStream继承自Stream。

var client = GetClient();
var remoteStream = client.GetDmtpRemoteStreamActor().LoadRemoteStream(new Metadata().AddOrUpdate("1", "1"));

byte[] data = new byte[] { 0, 1, 2, 3, 4 };
remoteStream.Write(data);

remoteStream.Position = 0;
byte[] buffer=new byte[5];
remoteStream.Read(buffer);

remoteStream.SafeDispose();

五、释放

断开连接,或者请求方主动调用Dispose时,响应方的Stream均会被实际的Dispose掉。

六、性能

图中示例为直接读取一个Window.iso文件所示。

本文示例Demo