vc++ 实现多线程断点续传.docx
《vc++ 实现多线程断点续传.docx》由会员分享,可在线阅读,更多相关《vc++ 实现多线程断点续传.docx(27页珍藏版)》请在冰点文库上搜索。
vc++实现多线程断点续传
vc++实现多线程断点续传
分类:
VC++编程技术2009-04-1610:
451210人阅读评论(5)收藏举报
结合本人的FTP类,http类,实现多线程断点续传
//DownloadMTR.cpp:
implementationoftheCDownloadMTRclass.
//
//////////////////////////////////////////////////////////////////////
#include"stdafx.h"
#include"downtest.h"
#include"DownloadMTR.h"
#include
#ifdef_DEBUG
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#definenewDEBUG_NEW
#endif
voidDownloadNotify(intnIndex,UINTnNotityType,LPVOIDlpNotifyData,LPVOIDpDownloadMTR);
//////////////////////////////////////////////////////////////////////
//Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDownloadMTR:
:
CDownloadMTR()
:
m_nThreadCount(DEFAULT_THREAD_COUNT)
,m_pDownloadPub_MTR(NULL)
,m_pDownloadPub_Info(NULL)
,m_pDownloadCellInfo(NULL)
,m_hThread(NULL)
,m_bForceDownload(FALSE)
,m_nTotalDownloadedSize_ThisTimes(0)
{
memset(&m_BaseDownInfo,0,sizeof(t_BaseDownInfo));
m_hEvtEndModule=:
:
CreateEvent(NULL,TRUE,FALSE,NULL);
m_dwDownloadStartTime=GetTickCount();
}
CDownloadMTR:
:
~CDownloadMTR()
{
StopDownload();
}
//
//设置下载的线程数
//
BOOLCDownloadMTR:
:
SetThreadCount(intnThreadCount)
{
if(nThreadCount<=0||nThreadCount>MAX_DOWNLOAD_THREAD_COUNT)
{
Log(L_WARNING,"Threadcount%disinvalid.Rang[%d-%d]",nThreadCount,1,MAX_DOWNLOAD_THREAD_COUNT);
returnFALSE;
}
if(nThreadCount==m_nThreadCount)
returnTRUE;
m_nThreadCount=nThreadCount;
returnTRUE;
}
//
//下载任务的线程函数
//
DWORDWINAPIThreadProc_DownloadMTR(
LPVOIDlpParameter //threaddata
)
{
CDownloadMTR*pDownloadMTR=(CDownloadMTR*)lpParameter;
ASSERT(pDownloadMTR);
pDownloadMTR->ThreadProc_DownloadMTR();
TRACE("下载任务的线程函数执行完毕/n");
returnTRUE;
}
BOOLCDownloadMTR:
:
ThreadProc_DownloadMTR()
{
//启动多线程下载任务
intnRet=StartMTRDownload();
if(nRet==2)returnHandleDownloadFinished(ENUM_DOWNLOAD_RESULT_SUCCESS);
if(nRet==0)returnHandleDownloadFinished(ENUM_DOWNLOAD_RESULT_FAILED);
//等待所有线程下载完成
ENUM_DOWNLOAD_RESULTeDownloadResult=WaitForDownloadFinished();
if(eDownloadResult==ENUM_DOWNLOAD_RESULT_SUCCESS&&!
GetDownloadResult())
{
eDownloadResult=ENUM_DOWNLOAD_RESULT_FAILED;
}
returnHandleDownloadFinished(eDownloadResult);
}
//
//多线程断点续传下载一个文件
//
BOOLCDownloadMTR:
:
Download(
LPCTSTRlpszDownloadURL,
LPCTSTRlpszSavePath,
LPCTSTRlpszSaveOnlyFileName,
LPCTSTRlpszUsername/*=NULL*/,
LPCTSTRlpszPassword/*=NULL*/,
BOOLbForceDownload/*=FALSE*/ //如果为TRUE表示强制性重新下载,以下载的部分将会被删除,FALSE表示断点续传
)
{
if(!
HANDLE_IS_VALID(m_hEvtEndModule))
returnFALSE;
if(!
lpszSavePath||strlen(lpszSavePath)<1)
returnFALSE;
m_csSavePath=lpszSavePath;
m_csSaveOnlyFileName=GET_SAFE_STRING(lpszSaveOnlyFileName);
m_bForceDownload=bForceDownload;
CStringcsServer,csObject;
USHORTnPort=0;
if(!
ParseURL(lpszDownloadURL,csServer,csObject,nPort,m_csProtocolType))
{
Log(L_ERROR,"DownloadURL[%s]invalid",lpszDownloadURL);
returnFALSE;
}
m_csDownloadURL=lpszDownloadURL;
//创建取站点信息对象
if(!
(m_pDownloadPub_Info=CreateDownloadObject()))
{
Log(L_ERROR,"Createdownloadobjectfailed");
returnHandleDownloadFinished(ENUM_DOWNLOAD_RESULT_FAILED);
}
//设置取站点信息对象的参数
m_pDownloadPub_Info->SetAuthorization(lpszUsername,lpszPassword);
m_pDownloadPub_Info->m_pDownloadMTR=this;
m_pDownloadPub_Info->SetDownloadUrl(lpszDownloadURL);
//创建一个下载线程
DWORDdwThreadId=0;
m_hThread=CreateThread(NULL,0,:
:
ThreadProc_DownloadMTR,LPVOID(this),0,&dwThreadId);
if(!
HANDLE_IS_VALID(m_hThread))
{
Log(L_WARNING,"Createdownloadthreadfailed");
returnFALSE;
}
returnTRUE;
}
//
//创建下载对象
//
CDownloadPub*CDownloadMTR:
:
CreateDownloadObject(intnCount/*=1*/)
{
if(nCount<1)returnNULL;
CDownloadPub*pDownloadPub=NULL;
if(m_csProtocolType.CompareNoCase("http")==0)
{
pDownloadPub=(CDownloadPub*)newCDownloadHttp[nCount];
}
elseif(m_csProtocolType.CompareNoCase("ftp")==0)
{
pDownloadPub=(CDownloadPub*)newCDownloadFtp[nCount];
}
elsereturnNULL;
returnpDownloadPub;
}
//
//删除下载对象
//
voidCDownloadMTR:
:
DeleteDownloadObject(CDownloadPub*pDownloadPub)
{
if(m_csProtocolType.CompareNoCase("http")==0)
{
delete[]((CDownloadHttp*)pDownloadPub);
}
elseif(m_csProtocolType.CompareNoCase("ftp")==0)
{
delete[]((CDownloadFtp*)pDownloadPub);
}
elsedelete[]pDownloadPub;
}
voidCallback_SaveDownloadInfo(intnIndex,intnDownloadedSize,intnSimpleSaveSize,WPARAMwParam)
{
CDownloadMTR*pDownloadMTR=(CDownloadMTR*)wParam;
ASSERT(pDownloadMTR);
pDownloadMTR->Callback_SaveDownloadInfo(nIndex,nDownloadedSize,nSimpleSaveSize);
}
voidCDownloadMTR:
:
Callback_SaveDownloadInfo(intnIndex,intnDownloadedSize,intnSimpleSaveSize)
{
if(nIndex>=0&&nIndex {
m_pDownloadCellInfo[nIndex].nDownloadedSize=nDownloadedSize;
if(nDownloadedSize>0)
{
m_CSFor_DownloadedData.Lock();
m_nTotalDownloadedSize_ThisTimes+=nSimpleSaveSize;
m_CSFor_DownloadedData.Unlock();
}
}
}
//
//创建多线程下载使用的对象和数据缓冲
//
BOOLCDownloadMTR:
:
CreateDownloadObjectAndDataMTR()
{
DeleteDownloadObjectAndDataMTR();
ASSERT(!
m_pDownloadPub_MTR&&m_pDownloadPub_Info);
m_pDownloadPub_MTR=CreateDownloadObject(m_nThreadCount);
//设置多线程下载使用的对象的参数
if(m_pDownloadPub_MTR)
{
for(intnIndex=0;nIndex {
m_pDownloadPub_MTR[nIndex].m_nIndex=nIndex;
m_pDownloadPub_MTR[nIndex].m_pDownloadMTR=this;
m_pDownloadPub_MTR[nIndex].Set_SaveDownloadInfo_Callback(:
:
Callback_SaveDownloadInfo,WPARAM(this));
m_pDownloadPub_MTR[nIndex].SetAuthorization(m_pDownloadPub_Info->Get_UserName(),m_pDownloadPub_Info->Get_GetPassword());
m_pDownloadPub_MTR[nIndex].SetDownloadUrl(m_csDownloadURL);
if(!
m_pDownloadPub_MTR[nIndex].SetSaveFileName(GetTempFilePath()))
returnFALSE;
}
}
//创建多线程下载使用的数据缓冲
ASSERT(!
m_pDownloadCellInfo);
m_pDownloadCellInfo=newt_DownloadCellInfo[m_nThreadCount];
if(m_pDownloadCellInfo)
memset(m_pDownloadCellInfo,0,m_nThreadCount*sizeof(t_DownloadCellInfo));
if(m_pDownloadPub_MTR!
=NULL&&m_pDownloadCellInfo!
=NULL)
returnTRUE;
Log(L_WARNING,"CreateMTRdownloadobjectorbufferfailed");
returnFALSE;
}
//
//删除多线程下载使用的对象和数据缓冲
//
voidCDownloadMTR:
:
DeleteDownloadObjectAndDataMTR()
{
if(m_pDownloadPub_MTR)
{
DeleteDownloadObject(m_pDownloadPub_MTR);
m_pDownloadPub_MTR=NULL;
}
if(m_pDownloadCellInfo)
{
delete[]m_pDownloadCellInfo;
m_pDownloadCellInfo=NULL;
}
}
//
//删除取站点信息的下载对象
//
voidCDownloadMTR:
:
DeleteDownloadObject_Info()
{
if(m_pDownloadPub_Info)
{
DeleteDownloadObject(m_pDownloadPub_Info);
m_pDownloadPub_Info=NULL;
}
}
//
//启动多线程下载,返回0表示失败,1表示成功,2表示不用下载了,因为该文件已经下载过了
//
intCDownloadMTR:
:
StartMTRDownload()
{
m_dwDownloadStartTime=GetTickCount();
DownloadNotify(-1,NOTIFY_TYPE_START_DOWNLOAD,(LPVOID)NULL,this);
//先获取站点信息
ASSERT(m_pDownloadPub_Info);
if(!
m_pDownloadPub_Info->GetRemoteSiteInfo())
return0;
DbgLog("要下载的文件大小是:
%d字节/n",m_pDownloadPub_Info->Get_FileTotalSize());
StandardSaveFileName();
CFileStatusfileStatus;
if(m_bForceDownload)
{
//需要重新下载
:
:
DeleteFile(m_csSavePathFileName);
:
:
DeleteFile(GetTempFilePath());
}
else
{
//要保存的文件是否已经存在,且大小和创建时间一致,如果不是强制性下载,则不需要再下载了。
if(CFile:
:
GetStatus(m_csSavePathFileName,fileStatus))
{
if (
(
fileStatus.m_mtime.GetTime()-m_pDownloadPub_Info->Get_TimeLastModified()<=2&&
m_pDownloadPub_Info->Get_TimeLastModified()-fileStatus.m_mtime.GetTime()<=2
)
&&
fileStatus.m_size==m_pDownloadPub_Info->Get_FileTotalSize()
&&
!
m_bForceDownload
)
{
return2;
}
}
}
BOOLbMustCreateNullFile=TRUE;
//读取下载信息,如果能读到说明上次下载尚未完成
if(!
m_bForceDownload&&m_pDownloadPub_Info->Is_SupportResume())
{
if(CFile:
:
GetStatus(GetTempFilePath(),fileStatus)&&
fileStatus.m_size==m_pDownloadPub_Info->Get_FileTotalSize()+GetDownloadInfoWholeSize())
{
if(ReadDownloadInfo())
bMustCreateNullFile=FALSE;
}
}
if(bMustCreateNullFile)
{
intnFileSize=m_pDownloadPub_Info->Get_FileTotalSize();
intnTempFileSize=nFileSize+GetDownloadInfoWholeSize();
if(nFileSize<0||!
m_pDownloadPub_Info->Is_SupportResume())
nTempFileSize=0;
//创建一个用来保存下载数据的空文件
if(!
CreateNullFile(GetTempFilePath(),nTempFileSize))
returnFALSE;
}
//分配下载任务
if(!
AssignDownloadTask())
{
Log(L_WARNING,"Assigntaskfailed");
return0;
}
m_dwDownloadStartTime=GetTickCount();
return1;
}
//
//得到临时数据保存的路径文件名
//
CStringCDownloadMTR:
:
GetTempFilePath()
{
ASSERT(!
m_csSavePathFileName.IsEmpty());
CStringcsTempFileName;
csTempFileName.Format("%s.~xhw~",m_csSavePathFileName);
:
:
SetFileAttributes(csTempFileName,FILE_ATTRIBUTE_HIDDEN);
returncsTempFileName;
}
//
//分配下载任务
//
BOOLCDownloadMTR:
:
AssignDownloadTask()
{
ASSERT(m_pDownloadPub_Info);
if(!
m_pDownloadPub_Info->Is_SupportResume())
{
DeleteDownloadObjectAndDataMTR();
Log(L_WARNING,"Site[%s]notsupportresumedownload",m_pDownloadPub_Info->Get_ServerName());
}
//文件大小未知,采用单线程
if(m_pDownloadPub_Info->Get_FileTotalSize()<=0||!
m_pDownloadPub_Info->Is_SupportResume())
{
if(m_nThreadCount!
=1)
{
DeleteDownloadObjectAndDataMTR();
SetThreadCount
(1);
}
}
if(!
DownloadInfoIsValid()||!
m_pDownloadPub_MTR||!
m_pDownlo