[置顶] libcurl实现多线程下载器


       libcurl官网(http://curl.haxx.se/)是一个很强大网络功能的库,支持当前DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP 等基本上网络大部分的协议,据说还是linux内置的基本库,其功能之强大可想而之,而且开源免费。

      前段时间项目要求来提高下载的速度,由于之前的下载做的很简单是基于QT的QNetWork组件来做的,这个下载器的功能比较单一,只支持单线程下载,所以下载速度在文件小的时候体现不出来,但在文件大的时候很明显比较慢,所以才产生了要更新下载器的想法,能够采用的库很多,但综合考虑,为了兼容多种系统,还是用开源的libcurl比较好。

    libcurl初始用起来很简单,要实现一个基本交互,只要进行基本的三步就可以: curl_easy_init、curl_easy_setopt、curl_easy_perform,这里关键在于curl_easy_setopt,这里面可以设置很多选项,你所要的功能基本上都在这里得到体现。闲话少说,现在库选好了,该谈谈策略的问题,既然采用多线程下载,总得有一个基本的思想,本项目中我的思路如下:对于一个指定长度的文件F,假如它的长度为L,若划分共n个线程来下,则每个线程负责下载的大小为L/n,就这样,线程1负责下载第一块L/n,线程2负责下载第二块L/n,依次类推,每个线程的负载都一样,这样设计比较简单,这样的设计避免了线程的切换,每个线程就是执行一个任务,就只下载自己所负责的那一区间。具体线程是采用pthread库,也是一个开源的,跟libcurl配合的很好。

    下载接收到的数据会写到一个临时文件里面去,临时文件的结构如下:

    [置顶] libcurl实现多线程下载器_第1张图片

   线程写数据区间对应线程的下载数据区间

   辅助信息X:存储每个线程的负责下载的开始位置begPos,要下载的数据长度blockLen,已经接收的数据长度recvLen

   辅助信息Y:要下载的文件长度L

   辅助信息是断点续传的根据

  临时文件结构定好,就开始下载了

一、正常下载流程

       正常下载流程包括初始化、线程下载区间划分、多线程下载数据,下载容错处理几方面

      1、下载初始化,主要为了获取下载的文件大小,下载是否支持多线程等属性;获取文件大小是为了确定划分线程个数,在本项目中线程最小分块为5M,即若一个下载文件大小为10M,则开两个线程,每个线程负责下载5M,若下载文件大小为11M,则就开线程个数为:11/5=2.2,即开3个线程,每个线程接收数据大小为11M/3,依次类推。

     判断是否支持多线程,是采用向服务端发送"Range:0-"请求,看返回的报文,若报文中有"Content-Range: bytes"部分,则表示服务器支持分片传输,即支持多线程下载,否则此资源链接只能采用单线程下载。

    2、线程下载区间划分:要所初始化得到的文件大小及是否支持多线程的属性来判断,若不支持多线程,那只能开一个线程,来下载整个文件;若支持多线程,则根据大小及线程最小分块来确定每个线程的下载区间,具体可参考1中说明

  3、多线程下载数据:根据1、2确定了每个线程的下载区间,就开相应个数的线程来执行下载,下载接收的数据全部写入临时文件,且要及时更新临时文件尾部信息

  4、下载容错处理:这个要重点说明一下,因为实际的网络环境都是很复杂的,网络性能也是时好时坏,所以一定要做好容错;本项目中的容错基本上主是增量重试

       若一次下载失败,就要等待一段时间来进行重试,这样虽然不能根治下载失败,但在很大程序上缓解了下载失败的可能。

二、断点续传流程

     断点续传跟正常下载不一样,它会先去读上一次的下载临时文件,重点是最临时文件尾部信息,来还原上一次下载时的场景,继续下载; 

     在这里特别要提一下:若上一次的下载是不支持断点绫传的,则会直接从0开始下载;否则是接着上次的进度开始下载。

三、下载注意事项:

    1、重定向的问题:重定向可以用curl中的选项CURLOPT_FOLLOWLOCATION来设置,也可以自己解析重定向后的URL

    2、下载中最好都用短连接,慎用长连接;

    3、下载中超时设置,可以用连接超时CURLOPT_CONNECTTIMEOUT项来设置,当然也可以设置CURLOPT_LOW_SPEED_LIMIT、CURLOPT_LOW_SPEED_TIME这两个选项来限制接收超时

四、总结:libcurl功能很强大,经测试速度比一般下载器要快一倍不止,文件越大,多线程的效能就越明显,下载本身并不复杂,但要优化性能的话,还需要做各种深究,如DNS缓存,连接重用等机制,这里恕在下才学浅,暂时未深究到这个层次。

源代码下载:http://download.csdn.net/detail/u012532305/9420166

欢迎大家拍砖!

  



你可能感兴趣的:(libcurl实现多线程下载)