随心所欲

做个幸福的人
posts - 147, comments - 1402, trackbacks - 28, articles - 0
  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理

断点续传、多线程上载

Posted on 2008-09-12 16:11 随心所欲 阅读(2479) 评论(13)  编辑 收藏 网摘 所属分类: 通讯/WebServerVS2005

现在已经有很多断点续传、多线程下载的软件了,比如网际快车等等。下面设计的程序是“断点续传、多线程上载”。

 

缘起:客户每天都有大量文件上传服务器。这些文件很多,并且体积挺大,FTP有时候会出一些问题,导致传递失败,要重新上传。

 

基本解决方案:

1:把文件分割成块,每次只是传递一个文件块。

2:一个文件可以起多个发送任务(线程),同时发送。

3:记录文件发送状态,在网络出现问题时(或者客户端意外终止),知道上次发送文件大小和位置指针。再重新链接以后,继续发送。

 

对象和线程

这里面涉及到一个显示窗体form1,有timer可以随时更新发送状态;一个上传类Uploader(对应于一个文件);Task对象(也就是一个文件);FileThunk对象(每一个任务,对应于一个线程);WebService接受文件类。

发送状态需要记录在数据库。测试状态下,数据记录在xml文件。基本格式如下:

      

Code

数据表结构也基本类似这样。

 

核心代码

1form1. 这个主要是显示。主要函数是 添加任务(Task);更新任务状态

 
浏览文件,创建任务
显示和更新状态,返回DataTable
执行任务


2:Uploader的核心代码:主要是启动线程。

Code


3:Task类的主要代码:主要是初始化任务,其他诸如和对数据的保存/提取 

Code


4:FileChunk的核心代码:主要是如何上传文件

Code



5:WebService的核心代码

Code



   小结

技术难度不大;现实实用;上传速度尚可。

  程序运行截图一个
file_uploader.jpg

Feedback

#1楼    回复  引用  查看    

2008-09-12 16:15 by Bob.Xie      
谢谢!
学习

我觉得放上源码下载会好一点

#2楼 [楼主]   回复  引用  查看    

2008-09-12 16:20 by 随心所欲      
@Bob.Xie
实际应用应该是存取到数据库的。现在是测试,所以我只是放在xml中。
再者,测试性代码,意义不大。
第三,俺以为 程序员多看看设计思路,要比下载源码好的多。

#3楼    回复  引用  查看    

2008-09-12 16:35 by 怪虎      
能放源码吗

#4楼    回复  引用  查看    

2008-09-12 17:02 by From Ocean      
几个问题:
1. 没看到异常处理,比如在当前连接当中重新发送其中一段文件
2. 客户端是如何处理续传的?通过查询数据库看记录数以及记录状态是否正确来判断么?

#5楼 [楼主]   回复  引用  查看    

2008-09-12 18:12 by 随心所欲      
@From Ocean
1: 异常处理在服务器端的webservice中。
这里出现异常的原因是:同时又多个线程写同一个文件。
处理方法简单:不做任何处理。也就是说客户端放弃这一次的操作,进入下一个循环,也就是重新再次发送(客户端循环时没有增加postion)。
2:是的,每一个timer事件里,我都把Task的当前状态保存到数据库。(t.Save())。 这样,如果网络断开,那么数据库将有最近2秒的状态。下一次链接时,从数据库加载这些状态,然后继续传递。

----
这些代码总共花了不到一天的时间,所以并不十分完善,但是思路是这个样子的。

#6楼    回复  引用  查看    

2008-09-12 20:25 by 回头望见你      
为什么要采用WS ?

#7楼    回复  引用  查看    

2008-09-13 08:44 by Jeffers Yuan      
在多线程的情况下,如果某一个线程的任务下载完之后,你如何重新指派一个新的任务给它,而原来的多个线程的任务又如何调整,恐怕这才是重点。

#8楼 [楼主]   回复  引用  查看    

2008-09-13 10:10 by 随心所欲      
@回头望见你
因为ws比较方便。
如果自己写socket,还得指定端口,又得设置防火墙打开该端口;还得设计简单的通讯协议,以及异常等等。
ws就用80端口,通用方便。

#9楼    回复  引用    

2008-09-13 10:14 by kisskiki [未注册用户]
@在多线程的情况下,如果某一个线程的任务下载完之后,你如何重新指派一个新的任务给它,而原来的多个线程的任务又如何调整,恐怕这才是重点。

仔细看代码就知道了,lz是先把所有文件分块,然后存到一个数组里面,然后每个文件块创建一个线程。

#10楼 [楼主]   回复  引用  查看    

2008-09-13 10:15 by 随心所欲      
@Jeffers Yuan
是的,调整线程是可以提高效率的。
现在的处理非常简单,等到一个线程运行结束的时候,我就kill了它。

以我的测试来看,在大量文件的时候,一个文件分2-3个线程上传是比较合理的,如果多过5个,服务器端同时写文件的可能性大大增加,并且客户端的响应也会因为几十个线程同时读文件而变得非常慢。
所以其他的线程也没有做什么调整,继续他们的任务就行了。2-3个线程,如果在结束一个,调整的必要性就不大了。

#11楼 [楼主]   回复  引用  查看    

2008-09-13 10:17 by 随心所欲      
@kisskiki
是的,每个文件分配固定的几个线程来处理。等到处理完成后就kill掉该线程。

#12楼    回复  引用    

2008-09-13 12:00 by jeffersyuan [未注册用户]
@随心所欲
简单的情况下,这种方法是没有问题的。但是,比如2-3个进程,由于不可预测的网络问题,很有可能某个进程很快下载完了,如果不调整进程的话,效率会非常低,尤其在文件比较大的情况下。

#13楼 [楼主]   回复  引用  查看    

2008-09-13 12:10 by 随心所欲      
@jeffersyuan
有道理。
再多一个线程,专门来检查各个线程的状态,如果有文件中的线程结束,则把剩余的部分再次分配线程。保持始终有足够多个线程的状态。

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:

相关链接: