多资源、多线程、断点续传

我要做一个支持多资源、多线程、断点续传的小工具,基于Python。Windows下有迅雷、FlashGet、QQ旋风(相当地泛滥),Linux下也有D4X,Axel ,aria2,那为什么还要写这样一个工具呢?

(1) 上面都不是Python写的。
(2) Linux下的下载工具都不能主动获取资源,而现在迅雷和FlashGet之所以快就是因为他们有资源。
(3) Linux下几个工具多线程、断点续传做的不太好。aria2似乎不错,不过我没编译过去,支持那么多协议,觉得有点臃肿。

其实从原理上讲,迅雷不过就是一个HTTP/FTP的多线程断点下载工具,现在做大了就来抢BT、电驴的用户,把这两个协议也加了进去。

前段时间看过axel,它的实现太简单了,只是固定的产生N个线程,然后把文件分成N块交给这些线程去下载。从迅雷的配置文件和下载的日志中可以看出来迅雷对下载文件的分块和线程的使用是有自己独有的方式(它线程下载的数据块有时很大4M,有时很小32K,即使在同一个线程中也是这样),我没办法知道迅雷是怎么做这个工作。所以我只能通过猜测和自己的一些想法来做这个工作。尽可能的保证合理的分块和线程使用。

创建一个下载管理器,包括配置信息,任务列表,一个具有速度值与使用次数的URL列表。

首先得到下载文件的大小(filesize),然后根据配置以及获得的URL数(N)对文件进行分块。
设置一个最小的分块值 MinPiece = 1024128 (最小分块大于filesize的5%)
设置一个最大的分块值 MaxPiece = 1024
1024*200

if filesize < = MinPiece:
不进行分块。选第一个地址进行下载,如果该地址下载超时则使用其它地址下载。(是否可以考虑使用N个地址同时下载?)

elif:
把文件分为N块,每块大小为Piece。
if Piece < MinPiece
把文件分为N-1块,Until Piece > MinPiece

if Piece > MaxPiece
把文件分为N+1块,Until Piece < MaxPiece

生成任务列表,一个任务包括:URL,filename,range[start,pos,end]
任务列表中对任务进行标记,DONE,RUNNING,PAUSE,STOP(需要这么多吗?)

根据获得的资源数产生N线程的线程池。

逐步向线程池中增加线程:前提是所有线程成功运行,则增加一个线程。
每个URL对应一个线程的上限数(5),总使用线程数固定(35)

线程运行时检查是否有空闲线程,如果有,则把自己的任务分割(分割的办法使用折半方式,同时要保证分块大于MinPiece),放在任务列表中,同时修改自己的任务的分段信息。
加入任务列表时从URL列表中选一个速度较快的URL,且该URL线程数未达到上限。(如何判断是否达到服务器支持连接数上限?如果针对某个URL创建新连接失败则标记该URL为不可再连接)

线程运行时检查缓冲区的大小,当大于write_buffer_size时则写文件(大于文件的10%时也写?),并且写记录文件,更新URL列表中的速度值,做这些操作时要使用锁机制。这个write_buffer_size根据不同的文件对应不同的大小(2M—>16M迅雷使用8-256)。写文件时可以直接seek到需要写入的位置,如果操作系统不支持这种方式,则先用0填充文件。

线程对失效的URL进行标记,对不支持断点续传的URL进行标记。考虑GBK,UTF-8编码。
线程完成时与停止时做写文件操作与上面操作相同。

记录文件中保存任务列表:
URL,filename,range[start,pos,end]
这样续传的时候程序就根据记录文件载入所有的任务,然后开启线程,进行下载。
记录文件使用MD5校验(最后一行存放前面信息的MD5值)。

一个线程如果速度过慢,则释放当前的任务,把它扔回任务列表中,标记该URL很慢,由空闲的线程再次开启这个任务,这时候有可能又由这个线程接管,但是使用的URL不同,因为扔回任务列表的时候会先一个较快的URL。

HTTP请求需要设置一个超时时间。


只是把我的一些想法在这里先记录下来,所以比较乱,做的时候可能还会有些变化。至少我目前觉得这种设计方式还是比较智能和高效的,欢迎大家拍砖,如果有好的建议我会记录下来。

Comments

bones7456: 支持!最近我也迷上了python…

est: 博主把flashget, 旋风的资源请求格式一锅端了吧。

timesking: 要在设计的时候做好强大的代理构想,我们很多人都在公司NTLM的防火墙后面。有时候用curl很好,但是就是断点续传麻烦。其他很多断点续传工具flashget等都无法使用NTLM代理。所以都无法使用

lun: 支持博主,linux下,下载效率不高,是个事实。

Zhangxj2008: 把设计的过程也写下来吧,用UMLChart。顺便开源,有很多人关注啊!

Zhangxj2008: 多看看网络蚂蚁有很多可以参考。但是P2P下载就不太明白了。

haoqiwawa: 设想挺有创意的。支持啊!

haoqiwawa: 我手机短信发不出去了,你忙完上QQ了叫我啊

草儿: 看来大体思路你是有了,就看下面怎么做了。希望能早日做出来。 其实可以先从简单做起,然后一步步丰富功能。

c: 没意思!只会抢占兄弟带宽资源!

shuge.lee: 支持 能开源和做成跨平台更好 舒阁(code.google.com/p/shuge)客户端对这样的下载工具有强烈的需求。

Amankwah: 多资源是怎么实现的?没有服务器,客户端自己去试?还是通过迅雷等的服务器来获取信息,或者是用搜索引擎自己分析? 另外,对这个相当感兴趣,考虑怎么管理这个项目?弄到Google code上去?sf上去?

M: 迅雷不仅仅是一个HTTP、FTP下载工具。对于下载过的文件,它进行摘要,从而可以识别网络上不同URL对应的相同文件,这从跟上本解决了多源的问题。如果只是分块下载,服务器端的带宽总是有限的。 在摘要的基础上,相同文件使用新的URL如何匹配摘要值这些都是一些具体的问题。

可可熊: http://cocobear.github.io/demo/pythunder/ 利用迅雷的资源。 google code,也不会是个大东西,一个小工具而已。不过最近一直忙公司的事。。。

deamon: 建议用Twisted(强大的网络框架), 可以单线程分块下载。 最近也想实现一个多线程下载工具用在自己的项目上。

ubunoon: NTLM本来就已经由这个库了,不过没有对线程进行Sleep。 python写的download工具,利用迅雷的资源,一个很好的方式,至少在国内,通吃了所有的http下载,只要用的人不是很多,楼主还是可以放心的。

坚持原创技术分享,您的支持将鼓励我继续创作!