UDP(Socket)异步传输文件

本文详细介绍了如何优化文件传输功能,包括解决大文件传输问题、实现多文件并行传输、添加传输进度条、确保文件完整性和安全性、处理文件传输中的丢包问题,以及实现文件传输过程的可视化和取消传输功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    目前要实现文件传输功能,之前用socket写了一个,能够实现基本的文件传输功能,也解决了大文件传输占据太多资源而卡死的问题(简单地创建一个新线程去专门接收大文件),但到了后面说要实现多文件传输,传输进度条的时候,发现自己对这一块不知道如何下手,于是在网上找了一篇还不错的文章:http://www.csharpwin.com/csharpresource/695.shtml,并且能够提供源代码下载。现在是把代码组织到自己的项目中,部分做了必要的修改,使得满足自己的需求,虽然有点地方还是看不懂,有些功能实现得不是那么好,但学到了很多东西,在这里记录一下。
    下面对原文章进行了适合自己口味的整理,在此谢谢原作。
    该例子实现了功能有:
    1.分别定义了文件发送管理类(SendFileManager),文件接收管理类(ReceiveFileManager),文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)。发送和读写文件都是基于异步的,实现了对大文件的分块发送。例子中还提供了一个发送文件端和接收文件端,都是用前面的几个类实现了文件的发送和接收。接受的文件默认放在桌面,文件名以下划线开始。
    2.添加了一个新的UdpPeer,实现了基本的异步传输和接收数据的方法,取代了之前用UdpClient来直接进行发送和接收。定义了一个接口IDataCell作为一个数据发送单元,它包含两个方法:ToBufferFromBuffer,所有的发送数据都继承它来实现。
       3. 在文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)中加入了Log事件,以便于我们了解文件的传输过程,在文件接收类(UdpRecieveFile)中还加入了RequestSendFile事件,当接收到一个发送文件请求时可以同意或者拒绝接收文件。
    4.实现多文件的传输必须加入每个发送数据属于哪个文件的标识,在文件接收时才能正确的处理这些数据,保证发送和接收的是同一个文件(没有被破坏和黑客入侵,安全考虑)。例子中是用文件的MD5值作为不同文件的数据标识的,这样当我们收到数据时,先根据MD5值判断数据属于哪一个文件,然后进行相应的处理。
    但是,由于大文件的MD5计算很耗时间,我在传送上百M的文件时窗口就出现了假死的情况。其实可以不用MD5,简单用GUID来标识文件。
    5.在实现多文件传输时,在文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)中,都用一个Dictionary<TKey, TValue>来存储文件对应的管理对象,TKey为文件的MD5,TValue就是发送文件和接收文件类对象了。当收到数据的时候,我们就根据数据中的MD5值找到对应的文件管理对象,进行相应的操作。当文件发送或者传输完毕后,我们就从Dictionary<TKey, TValue>中移除相应的对象并且清理它们所占的资源。
    当文件接收完成后,在ReceiveFileManager中新定义了一个事件ReceiveFileComplete,这个事件将对文件进行MD5校验,并且将结果通知我们,我们就可以知道文件是否完整的传输了过来。
    6.实现了一个显示文件传输过程信息的控件,它需要显示文件的图标、名称、大小、已经传输了的大小、文件的传输速度和一个进度条,进度条可以很直观的看到文件传输的完成量。其中获得文件的图标使用了Icon类的ExtractAssociatedIcon方法。
    7.在传输过程中取消文件的传送,有很多地方要考虑,最重要的就是要对数据的访问进行同步。当发送方取消发送时,要从文件发送列表中移除对应的发送文件管理类和移除传输控件,并且清理资源。在移除的时候,因为是异步收发信息的,也许其他地方还在申请使用这些资源,所以我们在移除的时候,不能让其他地方再访问他们,这里就要加上锁。清理发送文件管理类也一样,因为是异步读写文件的,我们清理的时候,需要等待正在读写的操作完成后才能进行清理,所以在发送文件管理类中加入了一个新的安全的Stream对象SafeStream,文件的读写都由他来操作。当接收方取消接收的时候,情形跟发送发一样,也需要进行类似的处理。
    8.实现了传输没有完成时,文件的后缀名改为.tmp。还实现了当选择的存储文件的目录下有相同的文件时,接收的文件将会以文件名_1.rar这样的方式保存。
    9.解决文件传输中的丢包问题,实现稳定的文件传输功能。
检测丢包采用的是在接受文件端来检测,当开始接收文件,收到一个数据包后,如果等待超过了一定时间后都没有收到数据包,就给发送方发送一个新的请求,要求继续发送文件,直到文件全部接收完成。具体的做法就是:
       1)ReceiveFileManager类中加入一个记录文件分块接收状态的列表Dictionary<intbool>int表示文件分块的序号,bool表示是否已经接收,初始化为全部没有接受(false)。
       2)ReceiveFileManager类中加入一个Timer,用来检测收到一个包后,等待的时间是否超过了设置的值,超过就给发送方发送数据包,请求继续发送文件,需要发送的文件块序号为从Dictionary<intbool>中查询出来的没有接收的文件块序号。

       3)如果Dictionary<intbool>中的所有文件块已经收到(全部为true),文件就接收完成了。

       按照以上的做法,就可以保证文件可以全部接收到了。

    以上基本上根据原文再加上自己在项目里实际情况整理的,再次感谢原作者。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值