|
|
多线程下载文件这个话题已经是老汤了。
在HTTP协议1.1中,允许通过增加一个HTTP Header“Range”来指定下载文件的区间。
所以一般的做法都是:
- 首先获取到文件大小(通过Content-Length)
- 开一个线程池在进行分块下载。
而在具体怎么实现的流程上,还是有差别的。
1. 标准的做法是:首先用一个线程发送HTTP GET指令,服务器会返回Content-Length,并能够根据协议判断出服务器是否支持Range。如果支持Range,则调配其它线程对后续部分分块下载。第一个线程继续下载第1块。
2. 还一种做法,首先发送HTTP HEAD指令,通过返回的Content-Length进行分块,调配线程进行下载。
这里提供一个类,属于第2种。
为了提高IO性能,类中可以使用内存映射文件方式进行操作。
<div class="highlighter">
- #ifndefCHTTPFILEDOWNLOADER_H_
- #defineCHTTPFILEDOWNLOADER_H_
- #include"Generic.h"
- classCHttpFileDownloader{
- public:
- CHttpFileDownloader();
- virtual~CHttpFileDownloader();
- booldownloadUrlToFile(constchar*lpszUrl,constchar*lpszFile);
- boolwaitForCompletion(void);
- private:
- stringm_strLocalFile;
- pthread_tm_lLeaderThread;
- structsockaddr_inm_stServerAddr;
- charm_szResourceURI[1024];
- charm_szDomain[1024];
- charm_szHost[1024];
- charm_szUrl[1024];
- sem_tm_stDownSem;
- pthread_mutex_tm_stDownloadThreadMutex;
- intm_nDownloadThreadCnt;
- boolm_bFailed;
- sem_tm_stCompleteSem;
- boolm_bSuccess;
- staticvoid*leaderThread(void*param);
- staticvoid*downloadThread(void*param);
- booldownloadProcess(void);
- voiddownloadBlock(unsignedchar*pMemory,intnRangeStart,intnRangeSize);
- boolsendBuffer(intnSocket,char*pBuf,intnSize);
- boolsendStringStream(intnSocket,stringstream&oStream);
- intrecvStringStream(intnSocket,stringstream&oStream);
- std::vector<string>parseResponse(stringstrResponse);
- boolisHttpStatusSuccess(string&strHttpResponse);
- stringgetHeaderValueByName(constchar*lpszHeader,std::vector<string>&vItems);
- };
- #endif/*CHTTPFILEDOWNLOADER_H_*/
|
|