C# 实现超大文件传输、断点续传等功能



一、说明

经常有小伙伴在开发控制台winformWPF等C/S软件时,会有文件传输的需求。正好TouchSocket完美支持这个,所以给大家介绍一波。


二、程序集源码

2.1 源码位置
2.2 说明文档

文档首页

三、安装

Nuget安装TouchSocket即可,具体步骤详看链接博客。

VS、Unity安装和使用Nuget包

四、特点

1.1 文件传输协议兼容性

RRQM文件传输使用的是特殊传输协议,与FTP,HTTP等协议完全不兼容,所以如果使用文件传输,则服务器与客户端必须均使用RRQM组件。

1.2 与FTP相比

因为RRQM使用的是特殊协议,所以性能、功能上要远强于FTP,且搭建简单,支持多通道传输等。

1.3 功能亮点
  • 简单易用。
  • 多线程处理。
  • 高性能,实测传输速度可达1000Mb/s
  • 超简单的传输限速设置,1k-10Gb 无级调节。
  • 超简单的传输速度、传输进度获取。
  • 随心所欲的暂停、继续、停止传输。
  • 系统化的权限管理,让敏感文件只允许私有化下载
  • RPC交互,让客户端和服务器交流不延迟。
  • 基于事件驱动,让每一步操作尽在掌握。
  • 超简单的断点续传设置,为大文件传输保驾护航。
  • 已经上传的文件,再次上传时,可实现快速上传
  • 极少的GC释放。

演示: 可以看到,下图正在上传一个Window的系统镜像文件,大约4.2Gb,传输速度已达到800Mb/s,GC基本上没有释放,性能非常强悍(中间有稍微停顿,因为程序在获取文件MD5值)。

在这里插入图片描述


四、创建服务器

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();
}

六、总结

实际上,文件传输功能,在客户端之间也可以直接传输,服务器也可以直接向客户端主动Pull、Push文件。而且,对于TouchRpc而言,文件传输也仅仅是的其中一个功能而已,更多的功能请在说明文档获取。

  • 16
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
C#实现文件传输断点续传功能,需要了解以下几个步骤: 1. 建立连接:使用 TCP 或 UDP 协议建立客户端与服务器之间的连接。 2. 发送文件信息:客户端向服务器发送文件名、大小、最后修改时间等信息。 3. 接收文件信息:服务器接收到文件信息后,根据文件名创建或打开文件,并记录已经传输的字节数。 4. 发送文件数据:客户端将文件数据拆分成多个数据块,每个数据块带上序号,发送给服务器。 5. 接收文件数据:服务器接收到数据块后,将其写入文件对应的位置,并记录已经接收到的字节数。 6. 检查数据是否完整:客户端和服务器都需要检查每个数据块是否已经成功接收,并进行重传或者继续传输剩余数据。 7. 断点续传:如果传输过程中出现异常,客户端和服务器可以记录已经传输的字节数,并在恢复连接后从该位置继续传输。 下面是一个简单的 C# 文件传输断点续传示例代码: ```csharp // 客户端代码 TcpClient client = new TcpClient(); client.Connect("127.0.0.1", 8888); NetworkStream stream = client.GetStream(); byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName); byte[] fileInfoBytes = BitConverter.GetBytes(fileSize); byte[] fileData = File.ReadAllBytes(fileName); stream.Write(fileNameBytes, 0, fileNameBytes.Length); stream.Write(fileInfoBytes, 0, fileInfoBytes.Length); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int bytesSent = 0; int totalBytesSent = 0; while (totalBytesSent < fileSize) { int bytesToSend = Math.Min(bufferSize, fileSize - totalBytesSent); Buffer.BlockCopy(fileData, totalBytesSent, buffer, 0, bytesToSend); stream.Write(buffer, 0, bytesToSend); totalBytesSent += bytesToSend; Console.WriteLine("Sent {0} bytes.", totalBytesSent); } stream.Close(); client.Close(); // 服务器端代码 TcpListener server = new TcpListener(IPAddress.Any, 8888); server.Start(); while (true) { TcpClient client = server.AcceptTcpClient(); NetworkStream stream = client.GetStream(); byte[] fileNameBytes = new byte[1024]; stream.Read(fileNameBytes, 0, fileNameBytes.Length); string fileName = Encoding.UTF8.GetString(fileNameBytes).Trim('\0'); byte[] fileSizeBytes = new byte[8]; stream.Read(fileSizeBytes, 0, fileSizeBytes.Length); long fileSize = BitConverter.ToInt64(fileSizeBytes, 0); FileStream fileStream = new FileStream(fileName, FileMode.Create); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int bytesReceived = 0; int totalBytesReceived = 0; while (totalBytesReceived < fileSize) { int bytesToReceive = Math.Min(bufferSize, (int)(fileSize - totalBytesReceived)); bytesReceived = stream.Read(buffer, 0, bytesToReceive); fileStream.Write(buffer, 0, bytesReceived); totalBytesReceived += bytesReceived; Console.WriteLine("Received {0} bytes.", totalBytesReceived); } stream.Close(); client.Close(); } ```
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若汝棋茗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值