说明
对点之间传输文件,操作基本完全一致,仅当两个TouchRpcClient相互传输文件时,需要多增加一个ID参数而已,所以下列示例仅演示由TcpTouchRpcClient到TcpTouchRpcService(实际上是TcpTouchRpcSocketClient)的操作。
对点之间可以任意pull(拉取)、push(推送)文件。接收对点可以订阅FileTransfering和FileTransfered事件,来获取相关信息,发起对点直接通过传输控制器或返回值获取传输信息。
值得注意的是,FileTransfered事件的触发并不意味着完成传输,具体结果还要通过Result属性值进行判断。
Pull文件
由TouchClient向TouchService发起Pull请求时,相当于由客户端从服务器下载文件。
响应流程:
- 发起Pull请求。
- 接收对点触发FileTransfering事件。
- 返回文件信息,然后检验是否续传等,然后开始接收。
- 接收完成或异常。
- 接收对点触发FileTransfered事件。
- 发起对点函数返回,控制器状态改变。
具体请求:
请求参数 | 参数属性 | 请求参数属性描述 |
---|---|---|
FileRequest | 参数描述 | FileRequest是请求信息类,主要向请求方描述请求详情。 |
Path | Path属性为请求文件在接收对点的路径,当该值为相对路径时,会与接收对点的RootPath组合路径。当为绝对路径时,则会直接访问路径文件(此时如果不在对点设置条件,则有可能会有文件安全隐患,设置详情链接)。 | |
SavePath | SavePath属性是发起对点本地的保存路径。 | |
Flags | 可通过叠加位域的形式,尝试断点续传。 | |
FileOperator | 参数描述 | FileOperator是本次传输的请求操作器,主要用于获取传输进度、速度、状态以及取消传输等操作。接收方的控制器从BeforeFileTransfer事件的参数e中获得。 |
CompletedLength | 已完成流长度。 | |
Speed 函数 | 从上次获取到此次获得的速度。一般请每秒钟调用一次获取速度值。 | |
PackageSize | 流分包尺寸。 | |
Progress | 传输进度,范围0-1。 | |
Result | 获取传输状态以及状态信息。当ResultCode为Default时,意味着传输正在进行。 | |
Token | CancellationToken类型的可取消令箭。 | |
Metadata | 参数描述 | string类型的键值对,用于和接收方交互数据。 |
示例代码:
【服务器】
static void Main(string[] args)
{
TcpTouchRpcService service = GetService();
service.Logger.Message("服务器成功启动");
Console.ReadKey();
}
static TcpTouchRpcService GetService()
{
var service = new RRQMConfig()//配置
.SetListenIPHosts(new IPHost[] { new IPHost(7789) })
.SetMaxCount(10000)
.SetThreadCount(100)
.SetSingletonLogger(new LoggerGroup(new ConsoleLogger(), new FileLogger()))
.SetVerifyToken("File")//连接验证口令。
.BuildWithTcpTouchRpcService();//此处build相当于new TcpTouchRpcService,然后Setup,然后Start。
service.Handshaked += (client, e) =>
{
client.Logger.Message($"有客户端成功验证,ID={client.ID}");
};
service.Disconnected += (client, e) =>
{
client.Logger.Message($"有客户端断开,ID={client.ID}");
};
service.FileTransfering += (client, e) =>
{
//有可能是上传,也有可能是下载
client.Logger.Message($"有客户端请求传输文件,ID={client.ID},请求类型={e.TransferType},请求文件名={e.FileRequest.Path}");
};
service.FileTransfered += (client, e) =>
{
//传输结束,但是不一定成功,需要从e.Result判断状态。
client.Logger.Message($"客户端传输文件结束,ID={client.ID},请求类型={e.TransferType},文件名={e.FileRequest.Path},请求状态={e.Result}");
};
return service;
}
【客户端】
static void Main(string[] args)
{
TcpTouchRpcClient client = new RRQMConfig()
.SetRemoteIPHost("127.0.0.1:7789")
.SetVerifyToken("File")
.BuildWithTcpTouchRpcClient();
client.FileTransfering += (client, e) =>
{
//有可能是上传,也有可能是下载
client.Logger.Message($"服务器请求传输文件,ID={client.ID},请求类型={e.TransferType},文件名={e.FileInfo.FileName}");
};
client.FileTransfered += (client, e) =>
{
//传输结束,但是不一定成功,需要从e.Result判断状态。
client.Logger.Message($"服务器传输文件结束,ID={client.ID},请求类型={e.TransferType},文件名={e.FileInfo.FileName},请求状态={e.Result}");
};
client.Logger.Message("连接成功");
//第一个参数是请求路径,第二个是保存路径。
FileRequest fileRequest = new FileRequest(@"D:\System\Windows.iso", $@"Windows.iso");
fileRequest.Flags = TransferFlags.BreakpointResume;//尝试断点续传,使用断点续传时,会验证MD5值
FileOperator fileOperator = new FileOperator();//实例化本次传输的控制器,用于获取传输进度、速度、状态等。
fileOperator.Timeout = 60 * 1000;//当传输大文件,且启用断点续传时,服务器可能会先计算MD5,而延时响应,所以需要设置超时时间。
//此处的作用相当于Timer,定时每秒输出当前的传输进度和速度。
LoopAction loopAction = LoopAction.CreateLoopAction(-1, 1000, (loop) =>
{
if (fileOperator.Result.ResultCode != ResultCode.Default)
{
loop.Dispose();
}
client.Logger.Message($"进度:{fileOperator.Progress},速度:{fileOperator.Speed()}");
});
loopAction.RunAsync();
Metadata metadata = new Metadata();//传递到服务器的元数据
metadata.Add("1", "1");
metadata.Add("2", "2");
//此方法会阻塞,直到传输结束,也可以使用PullFileAsync
IResult result = client.PullFile(fileRequest, fileOperator, metadata);
client.Logger.Message(result.ToString());
Console.ReadKey();
}
Push文件
Push和Pull操作一致,仅需要在最后调用PushFile即可。