📄 httpdownload.cpp
字号:
strVerb = _T("HEAD ");
else
strVerb = _T("GET ");
while (TRUE)
{
CString strSend,strAuth,strAddr,strHeader;
BYTE bAuth,bAtyp;
DWORD dwIP;
SOCKSREPPACKET pack;
int iStatus,nRet;;
char szReadBuf[1025];
DWORD dwContentLength,dwStatusCode;
m_dwFileDownloadedSize = 0;
m_dwDownloadSize = 0;
///////////////////////////////////////
// 目前的版本中,此信息并没有用
m_strHeader = _T("");
m_dwHeaderSize = 0;
//////////////////////////////////////
if (!CreateSocket())
return SENDREQUEST_FAIL;
if (m_bStopDownload)
return SENDREQUEST_STOP;
switch( m_nProxyType )
{
case PROXY_NONE:
if( TE_ConnectEx(m_hSocket,m_strServer,m_nPort,m_dwConnectTimeout,TRUE) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
break;
case PROXY_HTTPGET:
if( TE_ConnectEx(m_hSocket,m_strProxyServer,m_nProxyPort,m_dwConnectTimeout,TRUE) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
break;
case PROXY_SOCKS4A:
dwIP = TE_GetIP(m_strServer,TRUE);
if( dwIP == INADDR_NONE )
{
if( TE_ConnectEx(m_hSocket,m_strProxyServer,m_nProxyPort,m_dwConnectTimeout,TRUE) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( SOP_SendSocks4aReq(m_hSocket,CMD_CONNECT,m_nPort,m_strServer,m_strProxyUsername,m_dwSendTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
if( SOP_RecvPacket(m_pBSD,&pack,PACKET_SOCKS4AREP,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( !SOP_IsSocksOK(&pack,PACKET_SOCKS4AREP) )
return SENDREQUEST_ERROR;
break;// NOTICE:如果本地能够解析域名,可以使用SOCKS4 Proxy
}
case PROXY_SOCKS4:
// 必须要得到Proxy Server的IP地址(不能为域名)
dwIP = TE_GetIP(m_strServer,TRUE);
if( dwIP == INADDR_NONE )
return SENDREQUEST_ERROR;
if( TE_ConnectEx(m_hSocket,m_strProxyServer,m_nProxyPort,m_dwConnectTimeout,TRUE) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( SOP_SendSocks4Req(m_hSocket,CMD_CONNECT,m_nPort,dwIP,m_strProxyUsername,m_dwSendTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
if( SOP_RecvPacket(m_pBSD,&pack,PACKET_SOCKS4REP,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( !SOP_IsSocksOK(&pack,PACKET_SOCKS4REP) )
return SENDREQUEST_ERROR;
break;
case PROXY_SOCKS5:
if( TE_ConnectEx(m_hSocket,m_strProxyServer,m_nProxyPort,m_dwConnectTimeout,TRUE) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( m_bProxyAuthorization )
{
strAuth = _T("");
char c = (char)AUTH_NONE;
strAuth += c;
c = (char)AUTH_PASSWD;
strAuth += c;
}
else
{
char c = (char)AUTH_NONE;
strAuth = _T("");
strAuth += c;
}
bAuth =(BYTE)strAuth.GetLength();
if( SOP_SendSocks5AuthReq(m_hSocket,bAuth,(LPCTSTR)strAuth,m_dwSendTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
if( SOP_RecvPacket(m_pBSD,&pack,PACKET_SOCKS5AUTHREP,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( !SOP_IsSocksOK(&pack,PACKET_SOCKS5AUTHREP) )
return SENDREQUEST_ERROR;
switch( pack.socks5AuthRep.bAuth )
{
case AUTH_NONE:
break;
case AUTH_PASSWD:
if( !m_bProxyAuthorization )
return SENDREQUEST_FAIL;
if( SOP_SendSocks5AuthPasswdReq(m_hSocket,m_strProxyUsername,m_strProxyPassword,m_dwSendTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
if( SOP_RecvPacket(m_pBSD,&pack,PACKET_SOCKS5AUTHPASSWDREP,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( !SOP_IsSocksOK(&pack,PACKET_SOCKS5AUTHPASSWDREP) )
return SENDREQUEST_ERROR;
break;
case AUTH_GSSAPI:
case AUTH_CHAP:
case AUTH_UNKNOWN:
default:
return SENDREQUEST_FAIL;
break;
}
dwIP = TE_GetIP(m_strServer,TRUE);
if( dwIP != INADDR_NONE )
{
bAtyp = ATYP_IPV4ADDR;
strAddr = _T("");
// 转换字节序
dwIP = htonl(dwIP);
strAddr += (char)( (dwIP>>24) &0x000000ff);
strAddr += (char)( (dwIP>>16) &0x000000ff);
strAddr += (char)( (dwIP>>8 ) &0x000000ff);
strAddr += (char)( dwIP &0x000000ff);
}
else
{
bAtyp = ATYP_HOSTNAME;
char c = (char)m_strServer.GetLength();
strAddr = _T("");
strAddr += c;
strAddr += m_strServer;
}
if( SOP_SendSocks5Req(m_hSocket,CMD_CONNECT,bAtyp,(LPCTSTR)strAddr,m_nPort,m_dwSendTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
if( SOP_RecvPacket(m_pBSD,&pack,PACKET_SOCKS5REP,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( !SOP_IsSocksOK(&pack,PACKET_SOCKS5REP) )
return SENDREQUEST_ERROR;
break;
case PROXY_HTTPCONNECT:
default:
return SENDREQUEST_FAIL;
break;
}
if (m_bStopDownload)
return SENDREQUEST_STOP;
if( m_nProxyType == PROXY_HTTPGET )
{
strSend = strVerb + m_strDownloadUrl + " HTTP/1.1\r\n";
if( m_bProxyAuthorization )
{
strAuth = _T("");
Base64Encode(m_strProxyUsername+":"+m_strProxyPassword,strAuth);
strSend += "Proxy-Authorization: Basic "+strAuth+"\r\n";
}
}
else // No Proxy or not a HTTP_GET Proxy
strSend = strVerb + m_strObject + " HTTP/1.1\r\n";
if( m_bAuthorization )
{
strAuth = _T("");
Base64Encode(m_strUsername+":"+m_strPassword,strAuth);
strSend += "Authorization: Basic "+strAuth+"\r\n";
}
strSend += "Host: " + m_strServer + "\r\n";
strSend += "Accept: */*\r\n";
strSend += "Pragma: no-cache\r\n";
strSend += "Cache-Control: no-cache\r\n";
strSend += "User-Agent: "+m_strUserAgent+"\r\n";
if( !m_strReferer.IsEmpty() )
strSend += "Referer: "+m_strReferer+"\r\n";
strSend += "Connection: close\r\n";
// 查看文件已经下载的长度
CFileStatus fileDownStatus;
CString strRange;
strRange.Empty();
if (CFile::GetStatus(m_strTempSavePath,fileDownStatus) && !m_bForceDownload )
{
m_dwFileDownloadedSize = fileDownStatus.m_size;
if (m_dwFileDownloadedSize > 0)
{
strRange.Format(_T("Range: bytes=%d-\r\n"),m_dwFileDownloadedSize );
}
}
strSend += strRange;
//必须要加一个空行,否则Http服务器将不会应答
strSend += "\r\n";
//发送请求
nRet = TE_Send(m_hSocket,(LPCTSTR)strSend,strSend.GetLength(),m_dwSendTimeout);
if( nRet < strSend.GetLength() )
{
if ( TE_GetLastError() == WSAETIMEDOUT) // 超时
continue;
else // 其他错误,可能是网络断了,等待一段时间后重试
return SENDREQUEST_ERROR;
}
if (m_bStopDownload)
return SENDREQUEST_STOP;
strHeader.Empty();
while( TRUE )
{
ZeroMemory(szReadBuf,1025);
if( TE_BSocketGetStringEx(m_pBSD,szReadBuf,1024,&iStatus,m_dwReceiveTimeout) == SOCKET_ERROR )
return SENDREQUEST_ERROR;
if( szReadBuf[0] == '\0' ) // We have encountered "\r\n\r\n"
break;
strHeader += szReadBuf;
if( iStatus == 0)
strHeader += "\r\n";
}
///////////////////////////////////////
// 目前的版本中,此信息并没有用
m_strHeader = strHeader;
m_dwHeaderSize = m_strHeader.GetLength();
//////////////////////////////////////
nRet = GetInfo(strHeader,dwContentLength,dwStatusCode,m_TimeLastModified);
switch ( nRet )
{
case HTTP_FAIL:
return SENDREQUEST_FAIL;
break;
case HTTP_ERROR:
return SENDREQUEST_ERROR;
break;
case HTTP_REDIRECT:
continue;
break;
case HTTP_OK:
m_dwDownloadSize = dwContentLength;
// 应该判断一下服务器是否支持断点续传
if( strRange.IsEmpty() )
m_dwFileSize = dwContentLength; // 整个文件的长度
else
{
if ( dwStatusCode == 206 ) //支持断点续传
{
m_dwFileSize = m_dwFileDownloadedSize +dwContentLength;
m_bSupportResume = TRUE;
}
else //不支持断点续传
{
m_bSupportResume = FALSE;
m_dwFileDownloadedSize = 0; //不支持断点续传,此值要设为0
m_dwFileSize = dwContentLength;
}
}
return SENDREQUEST_SUCCESS;
break;
default:
return SENDREQUEST_FAIL;
break;
}
}// WHILE LOOP
return SENDREQUEST_SUCCESS;
}
// 设置代理及代理认证方式
void CHttpDownload::SetProxy(LPCTSTR lpszProxyServer, USHORT nProxyPort, BOOL bProxy, BOOL bProxyAuthorization, LPCTSTR lpszProxyUsername, LPCTSTR lpszProxyPassword,UINT nProxyType /*= PROXY_HTTPGET*/)
{
if( bProxy && lpszProxyServer != NULL)
{
m_bProxy = TRUE;
m_strProxyServer = lpszProxyServer;
m_nProxyPort = nProxyPort;
m_nProxyType = nProxyType;
if( bProxyAuthorization && lpszProxyUsername != NULL)
{
m_bProxyAuthorization = TRUE;
m_strProxyUsername = lpszProxyUsername;
m_strProxyPassword = lpszProxyPassword;
}
else
{
m_bProxyAuthorization = FALSE;
m_strProxyUsername = _T("");
m_strProxyPassword = _T("");
}
}
else
{
m_bProxy = FALSE;
m_bProxyAuthorization = FALSE;
m_nProxyPort = 0;
m_nProxyType = PROXY_NONE;
m_strProxyServer = _T("");
m_strProxyUsername = _T("");
m_strProxyPassword = _T("");
}
}
// 设置WWW认证信息
void CHttpDownload::SetAuthorization(LPCTSTR lpszUsername, LPCTSTR lpszPassword, BOOL bAuthorization)
{
if( bAuthorization && lpszUsername != NULL )
{
m_bAuthorization = TRUE;
m_strUsername = lpszUsername;
m_strPassword = lpszPassword;
}
else
{
m_bAuthorization = FALSE;
m_strUsername = _T("");
m_strPassword = _T("");
}
}
// 设置是否需要发送消息给调用窗口
void CHttpDownload::SetNotifyWnd(HWND hNotifyWnd, UINT nNotifyMsg, BOOL bNotify)
{
if( bNotify && (hNotifyWnd != NULL) && ::IsWindow(hNotifyWnd) )
{
m_bNotify = TRUE;
m_hNotifyWnd = hNotifyWnd;
m_nNotifyMessage = nNotifyMsg;
}
else
{
m_bNotify = FALSE;
m_hNotifyWnd = NULL;
m_nNotifyMessage = 0;
}
}
// 设置超时
void CHttpDownload::SetTimeout(DWORD dwSendTimeout, DWORD dwReceiveTimeout, DWORD dwConnectTimeout)
{
if( dwSendTimeout > 0 )
m_dwSendTimeout = dwSendTimeout;
if( dwReceiveTimeout > 0 )
m_dwReceiveTimeout = dwReceiveTimeout;
if( dwConnectTimeout > 0 )
m_dwConnectTimeout = dwConnectTimeout;
}
// 设置UserAgent
void CHttpDownload::SetUserAgent(LPCTSTR lpszUserAgent)
{
m_strUserAgent = lpszUserAgent;
if( m_strUserAgent.IsEmpty())
m_strUserAgent = _T("HttpDownload/2.0");
}
// 设置Referer
void CHttpDownload::SetReferer(LPCTSTR lpszReferer)
{
if( lpszReferer != NULL )
m_strReferer = lpszReferer;
else
m_strReferer = _T("");
}
// 设置重试的机制
// nRetryType = 0 不重试 RETRY_TYPE_NONE
// nRetryType = 1 重试一定次数 RETRY_TYPE_TIMES
// nRetryType = 2 永远重试(可能陷入死循环) RETRY_TYPE_ALWAYS
void CHttpDownload::SetRetry(UINT nRetryType, UINT nRetryDelay, UINT nRetryMax)
{
m_nRetryType = nRetryType;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -