#include <afxinet.h>
#define CHTTPDOWNLOAD_MINTHREADIDS 1
#define CHTTPDOWNLOAD_MAXTHREADIDS 5
#define CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION ".~tmp"
#define CHTTPDOWNLOAD_BUFFERSIZE 4096
#define CHTTPDOWNLOAD_EXCEPTION "ExceptionHTTPReceiveMonitor"
class CHttpDownloader
{
private:
struct BEGINEND
{
DWORD m_dwBegin;
DWORD m_dwEnd;
CString m_strSubRequestURLSaveAs;
CString m_strRequestURL;
CString m_strSession;
CString m_strRange;
CHttpDownloader * m_pOwner;
DWORD m_dwThreadOrder;
CString m_strServer;
INTERNET_PORT m_nPort;
CString m_strObject;
BOOL m_bCompleted;
};
CString m_strRequestURL; // 请求的URL
CString m_strRequestURLSaveAs; // URL另存为
CString m_strDefURLSaveAsPath; // URL另存为默认路径
DWORD m_dwServiceType; // URL协议类型
CString m_strServer; // URL服务器
CString m_strObject; // URL对象
INTERNET_PORT m_nPort; // RUL端口
DWORD m_dwSourceFileSize; // URL文件大小
DWORD m_dwBEGINENDs; // 区间数
CRITICAL_SECTION m_cs; // 临界区
BEGINEND * m_pBEGINEND; // 区间口地址
DWORD * m_pdwHTTPReceiveThreadID; // 线程ID
HANDLE * m_phHTTPReceiveThread; // 线程句柄
DWORD m_dwHTTPReceiveMonitorThreadID; // 线程ID
HANDLE m_hHTTPReceiveMonitorThread; // 线程句柄
private:
ULONGLONG ullGetSourceFileSize(LPCTSTR pstrServer,LPCTSTR pstrObject,INTERNET_PORT nPort)
{
ULONGLONG ullFilelength=0;
SYSTEMTIME st;
GetLocalTime(&st);
CString strLocalTime;
strLocalTime.Format("%u%u%u%u%u%u%u%u",st.wYear,st.wMonth,st.wDayOfWeek,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
CInternetSession session(strLocalTime);
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
DWORD dwRet=~HTTP_STATUS_OK;
CString strServerName=pstrServer;
pServer = session.GetHttpConnection(strServerName, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,pstrObject);
pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
if(dwRet == HTTP_STATUS_OK)
{
CString strRange;
if(pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,strRange,NULL))ullFilelength=atoull((LPSTR)(LPCSTR)strRange);
}
delete pFile;
delete pServer;
session.Close();
return ullFilelength;
}
ULONGLONG power(BYTE exp)
{
if(exp==0)return 1;
ULONGLONG ullRet=10;
for(BYTE i=1;i<exp;i++)ullRet*=10;
return ullRet;
}
ULONGLONG atoull(LPSTR pszInfo)
{
if(!pszInfo)return 0;
ULONGLONG ullRet=0;
CHAR szBuf[21]={0};
LPSTR pszBuf=szBuf;
while(*pszInfo!=0)*pszBuf++=*pszInfo++;
BYTE i=0;
pszBuf--;
while(pszBuf+1!=szBuf)ullRet+=(*pszBuf---48)*power(i++);
return ullRet;
}
DWORD dwtoa2(DWORD e,CHAR * c,DWORD l)
{
/* usage
CHAR c[12]={0}; //0~(1~10)~11
g_mdicreate.szTitle=&c[dwtoa2(++g_lWndNum,c,sizeof(c))];
*/
DWORD a=(DWORD)e;
DWORD aa=a;
if(aa<0)a*=-1;
DWORD b=-1;
DWORD cc=l-2;
while(1)
{
b=a%10;
a=a/10;
c[cc]=(CHAR)b+48;
cc--;
if (a==0)break;
}
aa>=0?cc++:c[cc]='-';
return cc;
}
BOOL bCalculateSegmentSize()
{
if(m_dwSourceFileSize<=0)return FALSE;
if(m_pBEGINEND)
{
delete[] m_pBEGINEND;
m_pBEGINEND=NULL;
}
m_dwBEGINENDs=m_dwSourceFileSize<=m_dwBEGINENDs?CHTTPDOWNLOAD_MINTHREADIDS:CHTTPDOWNLOAD_MAXTHREADIDS;
m_pBEGINEND=new BEGINEND[m_dwBEGINENDs];
m_dwSourceFileSize--;
DWORD m_dwAverageSegmentSize=m_dwSourceFileSize/m_dwBEGINENDs;
DWORD m_dwRemainderSegmentSize=m_dwSourceFileSize%m_dwBEGINENDs;
for (DWORD i=0,j=0,k=0;i<m_dwSourceFileSize && k<m_dwBEGINENDs;j=i+m_dwAverageSegmentSize,i=j,k++)
{
m_pBEGINEND[k].m_dwBegin=j;
m_pBEGINEND[k].m_dwEnd=m_pBEGINEND[k].m_dwBegin+m_dwAverageSegmentSize+(k==m_dwBEGINENDs-1?0:-1);
if(k==m_dwBEGINENDs-1)
{
if(m_dwRemainderSegmentSize)
{
m_pBEGINEND[k].m_dwEnd+=m_dwRemainderSegmentSize;
}
}
CHAR c[12]={0};
CHAR * pszNameOfFileWithFullPath=(CHAR *)(const CHAR *)m_strRequestURLSaveAs;
CHAR * pszFilePath=0;
GetFileInfo(pszNameOfFileWithFullPath,pszFilePath);
if(pszFilePath)
{
m_pBEGINEND[k].m_strSubRequestURLSaveAs.Format("%s//%s%s%s",pszFilePath,pszNameOfFileWithFullPath,&c[dwtoa2(k,c,sizeof(c))],CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION);
delete[]pszFilePath;
pszFilePath=0;
}
else
{
m_pBEGINEND[k].m_strSubRequestURLSaveAs.Format("%s//%s%s%s",m_strDefURLSaveAsPath,pszNameOfFileWithFullPath,&c[dwtoa2(k,c,sizeof(c))],CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION);
}
HANDLE hSubRequestURLSaveAs=CreateFile(m_pBEGINEND[k].m_strSubRequestURLSaveAs,FILE_ALL_ACCESS,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL);
if(INVALID_HANDLE_value!=hSubRequestURLSaveAs)
{
DWORD dwSubRequestURLSaveAsFileSize=GetFileSize(hSubRequestURLSaveAs,NULL);
if(INVALID_FILE_SIZE!=dwSubRequestURLSaveAsFileSize)
{
m_pBEGINEND[k].m_dwBegin+=dwSubRequestURLSaveAsFileSize;
}
CloseHandle(hSubRequestURLSaveAs);
}
m_pBEGINEND[k].m_strRequestURL=m_strRequestURL;
SYSTEMTIME st;
GetLocalTime(&st);
CString strLocalTime;
strLocalTime.Format("%u%u%u%u%u%u%u%u",st.wYear,st.wMonth,st.wDayOfWeek,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
m_pBEGINEND[k].m_strSession.Format("%s",strLocalTime);
m_pBEGINEND[k].m_strRange.Format("Range:bytes=%lu-%lu/r/n",m_pBEGINEND[k].m_dwBegin,m_pBEGINEND[k].m_dwEnd);
m_pBEGINEND[k].m_pOwner=this;
m_pBEGINEND[k].m_dwThreadOrder=k;
m_pBEGINEND[k].m_strServer=m_strServer;
m_pBEGINEND[k].m_nPort=m_nPort;
m_pBEGINEND[k].m_strObject=m_strObject;
m_pBEGINEND[k].m_bCompleted=FALSE;
printf("[%lu-%lu] %s/n",m_pBEGINEND[k].m_dwBegin,m_pBEGINEND[k].m_dwEnd,m_pBEGINEND[k].m_strSubRequestURLSaveAs);
}
return TRUE;
}
void GetFileInfo(CHAR * & pszNameOfFileWithFullPath,CHAR * & pszFilePath)
{
/* usage
CHAR * pszNameOfFileWithFullPath="E://Program Files//Thunder Network//Thunder//ThunderShell.exe";
CHAR * pszFilePath=0;
GetFileInfo(pszNameOfFileWithFullPath,pszFilePath);
if(pszFilePath)
{
printf("%s/n",pszNameOfFileWithFullPath);
printf("%s/n",pszFilePath);
delete[]pszFilePath;
pszFilePath=0;
}
*/
CHAR * pszWorkBuffer=0;
CHAR * pszNameOfFileWithFullPath2=0;
LONG lBufLength=1;
try
{
pszNameOfFileWithFullPath2=pszNameOfFileWithFullPath;
while(*pszNameOfFileWithFullPath2++!=0)++lBufLength;
if(lBufLength<=1)throw "exception@GetFileInfo";
pszWorkBuffer=new CHAR[lBufLength];
memset(pszWorkBuffer,0,lBufLength);
pszNameOfFileWithFullPath2=pszWorkBuffer;
while(*pszNameOfFileWithFullPath!=0)*pszNameOfFileWithFullPath2++=*pszNameOfFileWithFullPath++;
while (*--pszNameOfFileWithFullPath2!='//' && pszNameOfFileWithFullPath2>=pszWorkBuffer);
if(pszNameOfFileWithFullPath2<pszWorkBuffer)throw "exception@GetFileInfo";
*pszNameOfFileWithFullPath2=0;
pszNameOfFileWithFullPath=++pszNameOfFileWithFullPath2;
pszFilePath=pszWorkBuffer;
}
catch(...)
{
pszNameOfFileWithFullPath=0;
pszFilePath=0;
delete[]pszWorkBuffer;
pszWorkBuffer=0;
}
}
void ObtainDefURLSaveAsPath()
{
CHAR * pszCurrentDirectory=NULL;
DWORD dwLength=GetCurrentDirectory(0,NULL);
pszCurrentDirectory=new CHAR[dwLength];
GetCurrentDirectory(dwLength,pszCurrentDirectory);
m_strDefURLSaveAsPath.Format("%s",pszCurrentDirectory);
delete[] pszCurrentDirectory;
}
static DWORD WINAPI HTTPReceive(LPVOID lpParameter)
{
BEGINEND * pOwner=(BEGINEND *)lpParameter;
if(!pOwner)return -1;
DWORD k=pOwner->m_dwThreadOrder;
CInternetSession session(pOwner->m_strSession);
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
DWORD dwRet=~HTTP_STATUS_OK;
CString strServerName=pOwner->m_strServer;
pServer = session.GetHttpConnection(strServerName, pOwner->m_nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,pOwner->m_strObject);
pFile->AddRequestHeaders(pOwner->m_strRange);
printf("thread %d : %s/n",k,pOwner->m_strRange);
pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
if(dwRet == HTTP_STATUS_PARTIAL_CONTENT)
{
BYTE * pBuf=new BYTE[CHTTPDOWNLOAD_BUFFERSIZE];
FILE * pf=fopen(pOwner->m_strSubRequestURLSaveAs,"w+b");
if(pf)
{
UINT nRead = pFile->Read(pBuf, CHTTPDOWNLOAD_BUFFERSIZE);
while (nRead > 0)
{
fwrite(pBuf,1,nRead,pf);
nRead = pFile->Read(pBuf, CHTTPDOWNLOAD_BUFFERSIZE);
}
fclose(pf);
}
if(pBuf)delete[]pBuf;
}
delete pFile;
delete pServer;
session.Close();
pOwner->m_bCompleted=TRUE;
return 0;
}
static DWORD WINAPI HTTPReceiveMonitor(LPVOID lpParameter)
{
CHttpDownloader * pOwner=(CHttpDownloader*)lpParameter;
if(!pOwner)return -1;
if(!pOwner->m_dwBEGINENDs)return -1;
//
for(DWORD i=0;i<pOwner->m_dwBEGINENDs;i++)ResumeThread(pOwner->m_phHTTPReceiveThread[i]);
//
DWORD dwRet;
while(1)
{
dwRet=WaitForMultipleObjects(pOwner->m_dwBEGINENDs,pOwner->m_phHTTPReceiveThread,TRUE,20);
if(WAIT_OBJECT_0==dwRet)
{
BYTE * pBuf=new BYTE[CHTTPDOWNLOAD_BUFFERSIZE];
if(pBuf)
{
FILE * pf2=fopen(pOwner->m_strRequestURLSaveAs,"w+b");
if(pf2)
{
for(i=0;i<pOwner->m_dwBEGINENDs;i++)
{
if(pOwner->m_phHTTPReceiveThread[i])
{
CloseHandle(pOwner->m_phHTTPReceiveThread[i]);
pOwner->m_phHTTPReceiveThread[i]=NULL;
}
FILE * pf=fopen(pOwner->m_pBEGINEND[i].m_strSubRequestURLSaveAs,"r+b");
if(pf)
{
size_t r=fread(pBuf,1,CHTTPDOWNLOAD_BUFFERSIZE,pf);
while(r)
{
fwrite(pBuf,1,r,pf2);
r=fread(pBuf,1,CHTTPDOWNLOAD_BUFFERSIZE,pf);
}
fclose(pf);
//DeleteFile(pOwner->m_pBEGINEND[i].m_strSubRequestURLSaveAs);
}
}
fclose(pf2);
}
delete[] pBuf;
}
break;
}
else if(WAIT_TIMEOUT==dwRet)
{
DWORD dwBEGINENDs=pOwner->GetdwBEGINENDs();
if(0==dwBEGINENDs)
{
printf("%s/n","exception@creating thread");
throw CString(CHTTPDOWNLOAD_EXCEPTION);
return -1;
}
}
}
printf("%s all done!/npress any key to continue .../n",pOwner->m_strRequestURLSaveAs);
return 0;
}
DWORD GetdwBEGINENDs()
{
EnterCriticalSection(&m_cs);
DWORD dwBEGINENDs=m_dwBEGINENDs;
LeaveCriticalSection(&m_cs);
return dwBEGINENDs;
}
VOID SetdwBEGINENDs(DWORD dwBEGINENDs)
{
EnterCriticalSection(&m_cs);
m_dwBEGINENDs=dwBEGINENDs;
LeaveCriticalSection(&m_cs);
}
VOID ExceptionHTTPReceiveMonitor(DWORD dwExitCode)
{
if(m_phHTTPReceiveThread)
{
for(DWORD i=0;i<m_dwBEGINENDs;i++)
{
TerminateThread(m_phHTTPReceiveThread[i],dwExitCode);
CloseHandle(m_phHTTPReceiveThread[i]);
}
delete[] m_phHTTPReceiveThread;
m_phHTTPReceiveThread=NULL;
}
if (m_hHTTPReceiveMonitorThread)
{
TerminateThread(m_hHTTPReceiveMonitorThread,dwExitCode);
CloseHandle(m_hHTTPReceiveMonitorThread);
m_hHTTPReceiveMonitorThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
}
if(m_pdwHTTPReceiveThreadID)
{
delete[] m_pdwHTTPReceiveThreadID;
m_pdwHTTPReceiveThreadID=NULL;
}
if(m_pBEGINEND)
{
delete[] m_pBEGINEND;
m_pBEGINEND=NULL;
}
m_dwBEGINENDs=0;
m_pBEGINEND=NULL;
m_pdwHTTPReceiveThreadID=0;
m_phHTTPReceiveThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
m_hHTTPReceiveMonitorThread=NULL;
}
public:
CHttpDownloader()
{
m_dwBEGINENDs=0;
m_pBEGINEND=NULL;
m_pdwHTTPReceiveThreadID=0;
m_phHTTPReceiveThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
m_hHTTPReceiveMonitorThread=NULL;
InitializeCriticalSection(&m_cs);
}
~CHttpDownloader()
{
ExceptionHTTPReceiveMonitor(0);
DeleteCriticalSection(&m_cs);
}
VOID HTTPDownLoad(LPCTSTR pstrURL,LPCTSTR pstrURLSaveAs)
{
try
{
if(pstrURL==NULL || pstrURLSaveAs==NULL)return;
//
m_strRequestURL=pstrURL;
BOOL bRet=AfxParseURL(m_strRequestURL,m_dwServiceType,m_strServer,m_strObject,m_nPort); // AFXINET.H
if(!bRet)return;
if(AFX_INET_SERVICE_HTTP!=m_dwServiceType)return;
//
m_strRequestURLSaveAs=pstrURLSaveAs;
//
CHttpDownloader::ObtainDefURLSaveAsPath();
//
m_dwSourceFileSize=(DWORD)ullGetSourceFileSize(m_strServer,m_strObject,m_nPort);
if(!m_dwSourceFileSize)return;
//
if(!bCalculateSegmentSize())return;
//
if(!m_dwBEGINENDs || !m_pBEGINEND) return;
//
if (m_hHTTPReceiveMonitorThread)TerminateThread(m_hHTTPReceiveMonitorThread,0);
m_hHTTPReceiveMonitorThread=CreateThread(NULL,0,CHttpDownloader::HTTPReceiveMonitor,(LPVOID)this,0,&m_dwHTTPReceiveMonitorThreadID);
if (m_hHTTPReceiveMonitorThread)
{
m_pdwHTTPReceiveThreadID=new DWORD[m_dwBEGINENDs];
m_phHTTPReceiveThread=new HANDLE[m_dwBEGINENDs];
//
for(DWORD i=0;i<m_dwBEGINENDs;i++)
{
m_phHTTPReceiveThread[i]=NULL;
m_pdwHTTPReceiveThreadID[i]=0;
}
//
for(i=0;i<m_dwBEGINENDs;i++)
{
m_phHTTPReceiveThread[i]=CreateThread(NULL,0,CHttpDownloader::HTTPReceive,(LPVOID)&m_pBEGINEND[i],CREATE_SUSPENDED,&m_pdwHTTPReceiveThreadID[i]);
if (!m_phHTTPReceiveThread[i])
{
TerminateThread(m_hHTTPReceiveMonitorThread,-1);
for(i;i>=0;i--)
{
CloseHandle(m_phHTTPReceiveThread[i]);
m_phHTTPReceiveThread[i]=NULL;
m_pdwHTTPReceiveThreadID[i]=0;
}
SetdwBEGINENDs(0);
break;
}
}
//
CloseHandle(m_hHTTPReceiveMonitorThread);
m_hHTTPReceiveMonitorThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
}
}
catch(CString e)
{
if(e.CompareNoCase(CHTTPDOWNLOAD_EXCEPTION)==0)
{
ExceptionHTTPReceiveMonitor(-1);
}
}
}
};
INT main(INT argc, CHAR* argv[])
{
CHttpDownloader httpdownloader;
httpdownloader.HTTPDownLoad("
http://localhost:80/a.rar"
;,"c://测试.rar");
CHAR c;
scanf("%c",&c);
return 0;
}
#define CHTTPDOWNLOAD_MINTHREADIDS 1
#define CHTTPDOWNLOAD_MAXTHREADIDS 5
#define CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION ".~tmp"
#define CHTTPDOWNLOAD_BUFFERSIZE 4096
#define CHTTPDOWNLOAD_EXCEPTION "ExceptionHTTPReceiveMonitor"
class CHttpDownloader
{
private:
struct BEGINEND
{
DWORD m_dwBegin;
DWORD m_dwEnd;
CString m_strSubRequestURLSaveAs;
CString m_strRequestURL;
CString m_strSession;
CString m_strRange;
CHttpDownloader * m_pOwner;
DWORD m_dwThreadOrder;
CString m_strServer;
INTERNET_PORT m_nPort;
CString m_strObject;
BOOL m_bCompleted;
};
CString m_strRequestURL; // 请求的URL
CString m_strRequestURLSaveAs; // URL另存为
CString m_strDefURLSaveAsPath; // URL另存为默认路径
DWORD m_dwServiceType; // URL协议类型
CString m_strServer; // URL服务器
CString m_strObject; // URL对象
INTERNET_PORT m_nPort; // RUL端口
DWORD m_dwSourceFileSize; // URL文件大小
DWORD m_dwBEGINENDs; // 区间数
CRITICAL_SECTION m_cs; // 临界区
BEGINEND * m_pBEGINEND; // 区间口地址
DWORD * m_pdwHTTPReceiveThreadID; // 线程ID
HANDLE * m_phHTTPReceiveThread; // 线程句柄
DWORD m_dwHTTPReceiveMonitorThreadID; // 线程ID
HANDLE m_hHTTPReceiveMonitorThread; // 线程句柄
private:
ULONGLONG ullGetSourceFileSize(LPCTSTR pstrServer,LPCTSTR pstrObject,INTERNET_PORT nPort)
{
ULONGLONG ullFilelength=0;
SYSTEMTIME st;
GetLocalTime(&st);
CString strLocalTime;
strLocalTime.Format("%u%u%u%u%u%u%u%u",st.wYear,st.wMonth,st.wDayOfWeek,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
CInternetSession session(strLocalTime);
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
DWORD dwRet=~HTTP_STATUS_OK;
CString strServerName=pstrServer;
pServer = session.GetHttpConnection(strServerName, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,pstrObject);
pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
if(dwRet == HTTP_STATUS_OK)
{
CString strRange;
if(pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,strRange,NULL))ullFilelength=atoull((LPSTR)(LPCSTR)strRange);
}
delete pFile;
delete pServer;
session.Close();
return ullFilelength;
}
ULONGLONG power(BYTE exp)
{
if(exp==0)return 1;
ULONGLONG ullRet=10;
for(BYTE i=1;i<exp;i++)ullRet*=10;
return ullRet;
}
ULONGLONG atoull(LPSTR pszInfo)
{
if(!pszInfo)return 0;
ULONGLONG ullRet=0;
CHAR szBuf[21]={0};
LPSTR pszBuf=szBuf;
while(*pszInfo!=0)*pszBuf++=*pszInfo++;
BYTE i=0;
pszBuf--;
while(pszBuf+1!=szBuf)ullRet+=(*pszBuf---48)*power(i++);
return ullRet;
}
DWORD dwtoa2(DWORD e,CHAR * c,DWORD l)
{
/* usage
CHAR c[12]={0}; //0~(1~10)~11
g_mdicreate.szTitle=&c[dwtoa2(++g_lWndNum,c,sizeof(c))];
*/
DWORD a=(DWORD)e;
DWORD aa=a;
if(aa<0)a*=-1;
DWORD b=-1;
DWORD cc=l-2;
while(1)
{
b=a%10;
a=a/10;
c[cc]=(CHAR)b+48;
cc--;
if (a==0)break;
}
aa>=0?cc++:c[cc]='-';
return cc;
}
BOOL bCalculateSegmentSize()
{
if(m_dwSourceFileSize<=0)return FALSE;
if(m_pBEGINEND)
{
delete[] m_pBEGINEND;
m_pBEGINEND=NULL;
}
m_dwBEGINENDs=m_dwSourceFileSize<=m_dwBEGINENDs?CHTTPDOWNLOAD_MINTHREADIDS:CHTTPDOWNLOAD_MAXTHREADIDS;
m_pBEGINEND=new BEGINEND[m_dwBEGINENDs];
m_dwSourceFileSize--;
DWORD m_dwAverageSegmentSize=m_dwSourceFileSize/m_dwBEGINENDs;
DWORD m_dwRemainderSegmentSize=m_dwSourceFileSize%m_dwBEGINENDs;
for (DWORD i=0,j=0,k=0;i<m_dwSourceFileSize && k<m_dwBEGINENDs;j=i+m_dwAverageSegmentSize,i=j,k++)
{
m_pBEGINEND[k].m_dwBegin=j;
m_pBEGINEND[k].m_dwEnd=m_pBEGINEND[k].m_dwBegin+m_dwAverageSegmentSize+(k==m_dwBEGINENDs-1?0:-1);
if(k==m_dwBEGINENDs-1)
{
if(m_dwRemainderSegmentSize)
{
m_pBEGINEND[k].m_dwEnd+=m_dwRemainderSegmentSize;
}
}
CHAR c[12]={0};
CHAR * pszNameOfFileWithFullPath=(CHAR *)(const CHAR *)m_strRequestURLSaveAs;
CHAR * pszFilePath=0;
GetFileInfo(pszNameOfFileWithFullPath,pszFilePath);
if(pszFilePath)
{
m_pBEGINEND[k].m_strSubRequestURLSaveAs.Format("%s//%s%s%s",pszFilePath,pszNameOfFileWithFullPath,&c[dwtoa2(k,c,sizeof(c))],CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION);
delete[]pszFilePath;
pszFilePath=0;
}
else
{
m_pBEGINEND[k].m_strSubRequestURLSaveAs.Format("%s//%s%s%s",m_strDefURLSaveAsPath,pszNameOfFileWithFullPath,&c[dwtoa2(k,c,sizeof(c))],CHTTPDOWNLOAD_SUBURLSAVEASEXTENSION);
}
HANDLE hSubRequestURLSaveAs=CreateFile(m_pBEGINEND[k].m_strSubRequestURLSaveAs,FILE_ALL_ACCESS,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL);
if(INVALID_HANDLE_value!=hSubRequestURLSaveAs)
{
DWORD dwSubRequestURLSaveAsFileSize=GetFileSize(hSubRequestURLSaveAs,NULL);
if(INVALID_FILE_SIZE!=dwSubRequestURLSaveAsFileSize)
{
m_pBEGINEND[k].m_dwBegin+=dwSubRequestURLSaveAsFileSize;
}
CloseHandle(hSubRequestURLSaveAs);
}
m_pBEGINEND[k].m_strRequestURL=m_strRequestURL;
SYSTEMTIME st;
GetLocalTime(&st);
CString strLocalTime;
strLocalTime.Format("%u%u%u%u%u%u%u%u",st.wYear,st.wMonth,st.wDayOfWeek,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
m_pBEGINEND[k].m_strSession.Format("%s",strLocalTime);
m_pBEGINEND[k].m_strRange.Format("Range:bytes=%lu-%lu/r/n",m_pBEGINEND[k].m_dwBegin,m_pBEGINEND[k].m_dwEnd);
m_pBEGINEND[k].m_pOwner=this;
m_pBEGINEND[k].m_dwThreadOrder=k;
m_pBEGINEND[k].m_strServer=m_strServer;
m_pBEGINEND[k].m_nPort=m_nPort;
m_pBEGINEND[k].m_strObject=m_strObject;
m_pBEGINEND[k].m_bCompleted=FALSE;
printf("[%lu-%lu] %s/n",m_pBEGINEND[k].m_dwBegin,m_pBEGINEND[k].m_dwEnd,m_pBEGINEND[k].m_strSubRequestURLSaveAs);
}
return TRUE;
}
void GetFileInfo(CHAR * & pszNameOfFileWithFullPath,CHAR * & pszFilePath)
{
/* usage
CHAR * pszNameOfFileWithFullPath="E://Program Files//Thunder Network//Thunder//ThunderShell.exe";
CHAR * pszFilePath=0;
GetFileInfo(pszNameOfFileWithFullPath,pszFilePath);
if(pszFilePath)
{
printf("%s/n",pszNameOfFileWithFullPath);
printf("%s/n",pszFilePath);
delete[]pszFilePath;
pszFilePath=0;
}
*/
CHAR * pszWorkBuffer=0;
CHAR * pszNameOfFileWithFullPath2=0;
LONG lBufLength=1;
try
{
pszNameOfFileWithFullPath2=pszNameOfFileWithFullPath;
while(*pszNameOfFileWithFullPath2++!=0)++lBufLength;
if(lBufLength<=1)throw "exception@GetFileInfo";
pszWorkBuffer=new CHAR[lBufLength];
memset(pszWorkBuffer,0,lBufLength);
pszNameOfFileWithFullPath2=pszWorkBuffer;
while(*pszNameOfFileWithFullPath!=0)*pszNameOfFileWithFullPath2++=*pszNameOfFileWithFullPath++;
while (*--pszNameOfFileWithFullPath2!='//' && pszNameOfFileWithFullPath2>=pszWorkBuffer);
if(pszNameOfFileWithFullPath2<pszWorkBuffer)throw "exception@GetFileInfo";
*pszNameOfFileWithFullPath2=0;
pszNameOfFileWithFullPath=++pszNameOfFileWithFullPath2;
pszFilePath=pszWorkBuffer;
}
catch(...)
{
pszNameOfFileWithFullPath=0;
pszFilePath=0;
delete[]pszWorkBuffer;
pszWorkBuffer=0;
}
}
void ObtainDefURLSaveAsPath()
{
CHAR * pszCurrentDirectory=NULL;
DWORD dwLength=GetCurrentDirectory(0,NULL);
pszCurrentDirectory=new CHAR[dwLength];
GetCurrentDirectory(dwLength,pszCurrentDirectory);
m_strDefURLSaveAsPath.Format("%s",pszCurrentDirectory);
delete[] pszCurrentDirectory;
}
static DWORD WINAPI HTTPReceive(LPVOID lpParameter)
{
BEGINEND * pOwner=(BEGINEND *)lpParameter;
if(!pOwner)return -1;
DWORD k=pOwner->m_dwThreadOrder;
CInternetSession session(pOwner->m_strSession);
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
DWORD dwRet=~HTTP_STATUS_OK;
CString strServerName=pOwner->m_strServer;
pServer = session.GetHttpConnection(strServerName, pOwner->m_nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,pOwner->m_strObject);
pFile->AddRequestHeaders(pOwner->m_strRange);
printf("thread %d : %s/n",k,pOwner->m_strRange);
pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
if(dwRet == HTTP_STATUS_PARTIAL_CONTENT)
{
BYTE * pBuf=new BYTE[CHTTPDOWNLOAD_BUFFERSIZE];
FILE * pf=fopen(pOwner->m_strSubRequestURLSaveAs,"w+b");
if(pf)
{
UINT nRead = pFile->Read(pBuf, CHTTPDOWNLOAD_BUFFERSIZE);
while (nRead > 0)
{
fwrite(pBuf,1,nRead,pf);
nRead = pFile->Read(pBuf, CHTTPDOWNLOAD_BUFFERSIZE);
}
fclose(pf);
}
if(pBuf)delete[]pBuf;
}
delete pFile;
delete pServer;
session.Close();
pOwner->m_bCompleted=TRUE;
return 0;
}
static DWORD WINAPI HTTPReceiveMonitor(LPVOID lpParameter)
{
CHttpDownloader * pOwner=(CHttpDownloader*)lpParameter;
if(!pOwner)return -1;
if(!pOwner->m_dwBEGINENDs)return -1;
//
for(DWORD i=0;i<pOwner->m_dwBEGINENDs;i++)ResumeThread(pOwner->m_phHTTPReceiveThread[i]);
//
DWORD dwRet;
while(1)
{
dwRet=WaitForMultipleObjects(pOwner->m_dwBEGINENDs,pOwner->m_phHTTPReceiveThread,TRUE,20);
if(WAIT_OBJECT_0==dwRet)
{
BYTE * pBuf=new BYTE[CHTTPDOWNLOAD_BUFFERSIZE];
if(pBuf)
{
FILE * pf2=fopen(pOwner->m_strRequestURLSaveAs,"w+b");
if(pf2)
{
for(i=0;i<pOwner->m_dwBEGINENDs;i++)
{
if(pOwner->m_phHTTPReceiveThread[i])
{
CloseHandle(pOwner->m_phHTTPReceiveThread[i]);
pOwner->m_phHTTPReceiveThread[i]=NULL;
}
FILE * pf=fopen(pOwner->m_pBEGINEND[i].m_strSubRequestURLSaveAs,"r+b");
if(pf)
{
size_t r=fread(pBuf,1,CHTTPDOWNLOAD_BUFFERSIZE,pf);
while(r)
{
fwrite(pBuf,1,r,pf2);
r=fread(pBuf,1,CHTTPDOWNLOAD_BUFFERSIZE,pf);
}
fclose(pf);
//DeleteFile(pOwner->m_pBEGINEND[i].m_strSubRequestURLSaveAs);
}
}
fclose(pf2);
}
delete[] pBuf;
}
break;
}
else if(WAIT_TIMEOUT==dwRet)
{
DWORD dwBEGINENDs=pOwner->GetdwBEGINENDs();
if(0==dwBEGINENDs)
{
printf("%s/n","exception@creating thread");
throw CString(CHTTPDOWNLOAD_EXCEPTION);
return -1;
}
}
}
printf("%s all done!/npress any key to continue .../n",pOwner->m_strRequestURLSaveAs);
return 0;
}
DWORD GetdwBEGINENDs()
{
EnterCriticalSection(&m_cs);
DWORD dwBEGINENDs=m_dwBEGINENDs;
LeaveCriticalSection(&m_cs);
return dwBEGINENDs;
}
VOID SetdwBEGINENDs(DWORD dwBEGINENDs)
{
EnterCriticalSection(&m_cs);
m_dwBEGINENDs=dwBEGINENDs;
LeaveCriticalSection(&m_cs);
}
VOID ExceptionHTTPReceiveMonitor(DWORD dwExitCode)
{
if(m_phHTTPReceiveThread)
{
for(DWORD i=0;i<m_dwBEGINENDs;i++)
{
TerminateThread(m_phHTTPReceiveThread[i],dwExitCode);
CloseHandle(m_phHTTPReceiveThread[i]);
}
delete[] m_phHTTPReceiveThread;
m_phHTTPReceiveThread=NULL;
}
if (m_hHTTPReceiveMonitorThread)
{
TerminateThread(m_hHTTPReceiveMonitorThread,dwExitCode);
CloseHandle(m_hHTTPReceiveMonitorThread);
m_hHTTPReceiveMonitorThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
}
if(m_pdwHTTPReceiveThreadID)
{
delete[] m_pdwHTTPReceiveThreadID;
m_pdwHTTPReceiveThreadID=NULL;
}
if(m_pBEGINEND)
{
delete[] m_pBEGINEND;
m_pBEGINEND=NULL;
}
m_dwBEGINENDs=0;
m_pBEGINEND=NULL;
m_pdwHTTPReceiveThreadID=0;
m_phHTTPReceiveThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
m_hHTTPReceiveMonitorThread=NULL;
}
public:
CHttpDownloader()
{
m_dwBEGINENDs=0;
m_pBEGINEND=NULL;
m_pdwHTTPReceiveThreadID=0;
m_phHTTPReceiveThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
m_hHTTPReceiveMonitorThread=NULL;
InitializeCriticalSection(&m_cs);
}
~CHttpDownloader()
{
ExceptionHTTPReceiveMonitor(0);
DeleteCriticalSection(&m_cs);
}
VOID HTTPDownLoad(LPCTSTR pstrURL,LPCTSTR pstrURLSaveAs)
{
try
{
if(pstrURL==NULL || pstrURLSaveAs==NULL)return;
//
m_strRequestURL=pstrURL;
BOOL bRet=AfxParseURL(m_strRequestURL,m_dwServiceType,m_strServer,m_strObject,m_nPort); // AFXINET.H
if(!bRet)return;
if(AFX_INET_SERVICE_HTTP!=m_dwServiceType)return;
//
m_strRequestURLSaveAs=pstrURLSaveAs;
//
CHttpDownloader::ObtainDefURLSaveAsPath();
//
m_dwSourceFileSize=(DWORD)ullGetSourceFileSize(m_strServer,m_strObject,m_nPort);
if(!m_dwSourceFileSize)return;
//
if(!bCalculateSegmentSize())return;
//
if(!m_dwBEGINENDs || !m_pBEGINEND) return;
//
if (m_hHTTPReceiveMonitorThread)TerminateThread(m_hHTTPReceiveMonitorThread,0);
m_hHTTPReceiveMonitorThread=CreateThread(NULL,0,CHttpDownloader::HTTPReceiveMonitor,(LPVOID)this,0,&m_dwHTTPReceiveMonitorThreadID);
if (m_hHTTPReceiveMonitorThread)
{
m_pdwHTTPReceiveThreadID=new DWORD[m_dwBEGINENDs];
m_phHTTPReceiveThread=new HANDLE[m_dwBEGINENDs];
//
for(DWORD i=0;i<m_dwBEGINENDs;i++)
{
m_phHTTPReceiveThread[i]=NULL;
m_pdwHTTPReceiveThreadID[i]=0;
}
//
for(i=0;i<m_dwBEGINENDs;i++)
{
m_phHTTPReceiveThread[i]=CreateThread(NULL,0,CHttpDownloader::HTTPReceive,(LPVOID)&m_pBEGINEND[i],CREATE_SUSPENDED,&m_pdwHTTPReceiveThreadID[i]);
if (!m_phHTTPReceiveThread[i])
{
TerminateThread(m_hHTTPReceiveMonitorThread,-1);
for(i;i>=0;i--)
{
CloseHandle(m_phHTTPReceiveThread[i]);
m_phHTTPReceiveThread[i]=NULL;
m_pdwHTTPReceiveThreadID[i]=0;
}
SetdwBEGINENDs(0);
break;
}
}
//
CloseHandle(m_hHTTPReceiveMonitorThread);
m_hHTTPReceiveMonitorThread=NULL;
m_dwHTTPReceiveMonitorThreadID=0;
}
}
catch(CString e)
{
if(e.CompareNoCase(CHTTPDOWNLOAD_EXCEPTION)==0)
{
ExceptionHTTPReceiveMonitor(-1);
}
}
}
};
INT main(INT argc, CHAR* argv[])
{
CHttpDownloader httpdownloader;
httpdownloader.HTTPDownLoad("
http://localhost:80/a.rar"
;,"c://测试.rar");CHAR c;
scanf("%c",&c);
return 0;
}
HTTP多线程下载实现
1632

被折叠的 条评论
为什么被折叠?



