// HttpGet.cpp: 实现CHttpGet类.
//
#include "stdafx.h"
#include "HttpGet.h"
#include "DealSocket.h"
#include "myfile.h"
int CHttpGet::m_nCount;
DWORD CHttpGet::m_nFileLength;
//---------------------------------------------------------------------------
CHttpGet::CHttpGet()
{
m_nFileLength=0;
}
//---------------------------------------------------------------------------
CHttpGet::~CHttpGet()
{
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoadProxy(
CString strProxyAddr,
int nProxyPort,
CString strHostAddr,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum)
{
SOCKET hSocket;
hSocket=ConnectHttpProxy(strProxyAddr,nProxyPort);
if(hSocket == INVALID_SOCKET) return 1;
// 发送文件头,计算文件大小.
SendHttpHeader(hSocket,strHostAddr,strHttpAddr,strHttpFilename,0);
closesocket(hSocket);
HttpDownLoad(
strProxyAddr,
nProxyPort,
strHostAddr,
80, // 无效.
strHttpAddr,
strHttpFilename,
strWriteFileName,
nSectNum,
true);
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoadNonProxy(
CString strHostAddr,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum)
{
int nHostPort=80;
SOCKET hSocket;
hSocket=ConnectHttpNonProxy(strHostAddr,nHostPort);
if(hSocket == INVALID_SOCKET) return 1;
// 发送文件头,计算文件大小.
SendHttpHeader(hSocket,strHostAddr,strHttpAddr,strHttpFilename,0);
closesocket(hSocket);
HttpDownLoad(
TEXT(""), // 无效.
80, // 无效.
strHostAddr,
nHostPort,
strHttpAddr,
strHttpFilename,
strWriteFileName,
nSectNum,
false);
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoad(
CString strProxyAddr,
int nProxyPort,
CString strHostAddr,
int nHostPort,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum,
BOOL bProxy)
{
ASSERT(nSectNum>0);
m_nCount=0; // 把计数器清零.
sectinfo=new CHttpSect[nSectNum]; // 给信息结构申请内存.
DWORD nSize= m_nFileLength/nSectNum; // 计算分割段的大小.
int i;
// 创建线程.
for(i=0;i<nSectNum;i++)
{
sectinfo[i].szProxyAddr=strProxyAddr; // 代理服务器地址.
sectinfo[i].nProxyPort =nProxyPort; // Host地址.
sectinfo[i].szHostAddr =strHostAddr; // Http文件地址.
sectinfo[i].nHostPort =nHostPort; // Http文件名.
sectinfo[i].szHttpAddr =strHttpAddr; // 代理服务端口号.
sectinfo[i].szHttpFilename=strHttpFilename;// Host端口号.
sectinfo[i].bProxyMode=bProxy; // 下载模态.
// 计算临时文件名.
CString strTempFileName;
strTempFileName.Format("%s_%d",strWriteFileName, i);
sectinfo[i].szDesFilename=strTempFileName; // 下载后的文件名.
if(i<nSectNum-1){
sectinfo[i].nStart=i*nSize; // 分割的起始位置.
sectinfo[i].nEnd=(i+1)*nSize; // 分割的终止位置.
}
else{
sectinfo[i].nStart=i*nSize; // 分割的起始位置.
sectinfo[i].nEnd=m_nFileLength; // 分割的终止位置.
}
// AfxBeginThread(ThreadDownLoad,§info[i],THREAD_PRIORITY_HIGHEST);
AfxBeginThread(ThreadDownLoad,§info[i]);
}
// 等待所有线程结束.
while(m_nCount!=nSectNum);
FILE *fpwrite;
// 打开写文件.
if((fpwrite=fopen(strWriteFileName,"wb"))==NULL){
return FALSE;
}
for(i=0;i<nSectNum;i++){
FileCombine(§info[i],fpwrite);
}
fclose(fpwrite);
delete[] sectinfo;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::FileCombine(CHttpSect *pInfo, FILE *fpwrite)
{
FILE *fpread;
// 打开文件.
if((fpread=fopen(pInfo->szDesFilename,"rb"))==NULL)
return FALSE;
DWORD nPos=pInfo->nStart;
// 设置文件写指针起始位置.
fseek(fpwrite,nPos,SEEK_SET);
int c;
// 把文件数据写入到子文件.
while((c=fgetc(fpread))!=EOF)
{
fputc(c,fpwrite);
nPos++;
if(nPos==pInfo->nEnd) break;
}
fclose(fpread);
DeleteFile(pInfo->szDesFilename);
return TRUE;
}
//---------------------------------------------------------------------------
UINT CHttpGet::ThreadDownLoad(void* pParam)
{
CHttpSect *pInfo=(CHttpSect*)pParam;
SOCKET hSocket;
if(pInfo->bProxyMode){
hSocket=ConnectHttpProxy(pInfo->szProxyAddr,pInfo->nProxyPort);
}
else{
hSocket=ConnectHttpNonProxy(pInfo->szHostAddr,pInfo->nHostPort);
}
if(hSocket == INVALID_SOCKET) return 1;
// 计算临时文件大小.
DWORD nFileSize=myfile.GetFileSizeByName(pInfo->szDesFilename);
DWORD nSectSize=(pInfo->nEnd)-(pInfo->nStart);
// 此段已下载完毕.
if(nFileSize==nSectSize){
TRACE("文件已下载完毕!\n");
CHttpGet::m_nCount++; // 计数.
return 0;
}
FILE *fpwrite=myfile.GetFilePointer(pInfo->szDesFilename);
if(!fpwrite) return 1;
// 设置下载范围.
SendHttpHeader(hSocket,pInfo->szHostAddr,pInfo->szHttpAddr,
pInfo->szHttpFilename,pInfo->nStart+nFileSize);
DWORD nLen;
DWORD nSumLen=0;
char szBuffer[1024];
while(1)
{
if(nSumLen>=nSectSize-nFileSize) break;
nLen=recv(hSocket,szBuffer,sizeof(szBuffer),0);
if (nLen == SOCKET_ERROR){
TRACE("Read error!\n");
fclose(fpwrite);
return 1;
}
if(nLen==0) break;
nSumLen +=nLen;
TRACE("%d\n",nLen);
// 把数据写入文件.
fwrite(szBuffer,nLen,1,fpwrite);
}
fclose(fpwrite); // 关闭写文件.
closesocket(hSocket); // 关闭套接字.
CHttpGet::m_nCount++; // 计数.
return 0;
}
//---------------------------------------------------------------------------
SOCKET CHttpGet::ConnectHttpProxy(CString strProxyAddr,int nPort)
{
TRACE("正在建立连接\n");
CString sTemp;
char cTmpBuffer[1024];
SOCKET hSocket=dealsocket.GetConnect(strProxyAddr,nPort);
if(hSocket == INVALID_SOCKET)
{
TRACE("连接http服务器失败!\n");
return INVALID_SOCKET;
}
// 发送CONNCET请求令到代理服务器,用于和代理建立连接代理服务器的
// 地址和端口放在strProxyAddr,nPort 里面.
sTemp.Format("CONNECT %s:%d HTTP/1.1\r\nUser-Agent:\
MyApp/0.1\r\n\r\n",strProxyAddr,nPort);
if(!SocketSend(hSocket,sTemp))
{
TRACE("连接代理失败\n");
return INVALID_SOCKET;
}
// 取得代理响应,如果连接代理成功,代理服务器将
// 返回"200 Connection established".
int nLen=GetHttpHeader(hSocket,cTmpBuffer);
sTemp=cTmpBuffer;
if(sTemp.Find("HTTP/1.0 200 Connection established",0)==-1)
{
TRACE("连接代理失败\n");
return INVALID_SOCKET;
}
TRACE(sTemp);
TRACE("代理连接完成\n");
return hSocket;
}
//---------------------------------------------------------------------------
SOCKET CHttpGet::ConnectHttpNonProxy(CString strHostAddr,int nPort)
{
TRACE("正在建立连接\n");
SOCKET hSocket=dealsocket.GetConnect(strHostAddr,nPort);
if(hSocket == INVALID_SOCKET)
return INVALID_SOCKET;
return hSocket;
}
//---------------------------------------------------------------------------
// 例如: strHostAddr="www.aitenshi.com",
// strHttpAddr="http://www.aitenshi.com/bbs/images/",
// strHttpFilename="pics.jpg".
BOOL CHttpGet::SendHttpHeader(SOCKET hSocket,CString strHostAddr,
CString strHttpAddr,CString strHttpFilename,DWORD nPos)
{
// 进行下载.
static CString sTemp;
char cTmpBuffer[1024];
// Line1: 请求的路径,版本.
sTemp.Format("GET %s%s HTTP/1.1\r\n",strHttpAddr,strHttpFilename);
if(!SocketSend(hSocket,sTemp)) return FALSE;
// Line2:主机.
sTemp.Format("Host: %s\r\n",strHostAddr);
if(!SocketSend(hSocket,sTemp)) return FALSE;
// Line3:接收的数据类型.
sTemp.Format(
- 1
- 2
前往页