18,356
社区成员
发帖
与我相关
我的任务
分享
BOOL CAsyncHttp::AsyncHttpSetHeader(char* strHeader)
{
if( !HttpAddRequestHeaders(m_hRequest,strHeader,-1,HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE))
{
TRACE("ERROR: HttpAddRequestHeaders failed \n");
return FALSE;
}
return TRUE;
}
BOOL CAsyncHttp::AsyncHttpSendRequest(char* strBody,int aiLen)
{
ResetEvent(m_hEventReqOK);
resend:
BOOL bRequest = HttpSendRequest(m_hRequest,"\r\n\r\n",4,strBody,aiLen);
if(!bRequest)
{
if(ERROR_IO_PENDING == GetLastError())
{
if(WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
{
TRACE( "WARMING: HttpSendRequest failed, maybe timeout \n");
return FALSE;
}
}
else
{
TRACE("ERROR: HttpSendRequest failed \n");
return FALSE;
}
}
if (m_bSetProxy)
{
DWORD dwStatus;
DWORD dwStatusSize = sizeof(dwStatus);
HttpQueryInfo(m_hRequest,HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,&dwStatus,&dwStatusSize,NULL);
switch (dwStatus)
{
case HTTP_STATUS_PROXY_AUTH_REQ :
{
InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());
InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_PASSWORD,(LPVOID)m_strProxyUserPass.c_str(),m_strProxyUserPass.length());
goto resend;
break;
}
case HTTP_STATUS_DENIED :
{
InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());
InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_PASSWORD,(LPVOID)m_strProxyUserPass.c_str(),m_strProxyUserPass.length());
goto resend;
break;
}
}
}
return TRUE;
}
string& CAsyncHttp::AsyncHttpRecieveResponse()
{
char szBuff [ASYNC_HTTP_BUFFER_SIZE + 1] = {0};
while(true)
{
INTERNET_BUFFERS stIB = {0};
stIB.dwStructSize = sizeof(INTERNET_BUFFERS);
stIB.lpvBuffer = szBuff;
stIB.dwBufferLength = ASYNC_HTTP_BUFFER_SIZE;
ResetEvent( m_hEventReqOK );
if( !::InternetReadFileExA(m_hRequest,&stIB,IRF_ASYNC,(LPARAM)this))
{
if(ERROR_IO_PENDING == GetLastError())
{
if(WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
{
TRACE("WARMING: InternetReadFileExA failed, maybe timeout \n");
break;
}
}
else
{
TRACE("ERROR: InternetReadFileExA failed \n");
break;
}
}
szBuff[stIB.dwBufferLength] = 0;
if (stIB.dwBufferLength == 0)
{
break;
}
m_strResponse.append(szBuff,stIB.dwBufferLength);
}
return m_strResponse;
}
void CALLBACK CAsyncHttp::AsyncInternetCallback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
CAsyncHttp* pObj = (CAsyncHttp*)dwContext;
switch(dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED :
{
pObj->m_hRequest = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwResult);
break;
}
case INTERNET_STATUS_HANDLE_CLOSING :
{
SetEvent(pObj->m_hEventAbort);
break;
}
case INTERNET_STATUS_REQUEST_COMPLETE :
{
if (ERROR_SUCCESS == ((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwError)
{
SetEvent(pObj-> m_hEventReqOK);
}
else
{
//如果发生错误,则处理错误事件
//这里也是一个陷阱,经常会忽视处理这个错误,
pObj->m_dwErrorCode = ASYNC_HTTP_ERR_OTHER;
SetEvent(pObj->m_hEventReqFail);
}
break;
}
default:
{
break;
}
}
return;
}
BOOL CAsyncHttp::WaitAsyncEvent(DWORD dwTimeOut,DWORD dwContext)
{
CAsyncHttp* pObj = (CAsyncHttp*)dwContext;
HANDLE hEvents[] = {pObj->m_hEventAbort,pObj->m_hEventReqFail,pObj->m_hEventReqOK};
DWORD dwRet = WaitForMultipleObjects(3,hEvents,FALSE,INFINITE);
switch(dwRet)
{
case WAIT_TIMEOUT:
{
//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_TIMEOUT; // 超时错误
return TRUE;
}
case WAIT_OBJECT_0:
{
//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_CANCEL; // 终止当前操作
return TRUE;
}
case WAIT_OBJECT_0+1:
{
//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_NET; // 完成网络操作失败
return TRUE;
}
case WAIT_OBJECT_0+2: // 完成网络操作成功
{
break;
}
}
return FALSE;
}
void CAsyncHttp::AsyncHttpCloseConn()
{
if(NULL != m_hRequest)
{
InternetCloseHandle(m_hRequest);
m_hRequest = NULL;
}
if(NULL != m_hSession)
{
InternetSetStatusCallback(m_hSession,NULL);
m_hSession = NULL;
}
if(m_hEventAbort)
{
CloseHandle(m_hEventAbort);
m_hEventAbort = NULL;
}
if(m_hEventReqFail)
{
CloseHandle(m_hEventReqFail);
m_hEventAbort = NULL;
}
if(m_hEventReqOK)
{
CloseHandle(m_hEventReqOK);
m_hEventAbort = NULL;
}
}
BOOL CAsyncHttp::AsyncHttpSetProxy(string& strProxyServer,long lProxyPort,string& strProxyUser,string& strProxyUserPass)
{
//参数正确性检查
if (strProxyServer.empty())
{
return FALSE;
}
//赋值
m_bSetProxy = TRUE;
m_strProxyServer = strProxyServer;
m_lProxyPort = lProxyPort;
m_strProxyUser = strProxyUser;
m_strProxyUserPass = strProxyUserPass;
return TRUE;
}
BOOL CAsyncHttp::AsyncHttpSetProxyOff()
{
//赋值
m_bSetProxy = FALSE;
return TRUE;
}
using namespace std;
CAsyncHttp::CAsyncHttp() : m_bSetProxy(FALSE) //确认是否设置了代理
, m_strProxyServer("") //代理服务器的地址
, m_lProxyPort(8080) //代理服务器的端口
, m_strProxyUser("") //登录代理服务器的用户名
, m_strProxyUserPass("") //登录代理服务器的用户密码
{
m_hSession = NULL;
m_hConnect = NULL;
m_hRequest = NULL;
m_hEventAbort = ::CreateEvent(NULL,TRUE,FALSE,NULL);
m_hEventReqFail = ::CreateEvent(NULL,TRUE,FALSE,NULL);
m_hEventReqOK = ::CreateEvent(NULL,TRUE,FALSE,NULL);
m_dwErrorCode = ASYNC_HTTP_OK;
}
CAsyncHttp::~CAsyncHttp()
{
AsyncHttpCloseConn();
}
BOOL CAsyncHttp::AsyncHttpOpen()
{
string strProxyInfo;
if (m_bSetProxy)
{
strProxyInfo.clear();
strProxyInfo = m_strProxyServer;
strProxyInfo.append(":");
CString strPort;
strPort.Format("%ld",m_lProxyPort);
strProxyInfo.append((LPCSTR)strPort);
m_hSession = InternetOpen("xihu",INTERNET_OPEN_TYPE_PROXY,strProxyInfo.c_str() ,NULL,INTERNET_FLAG_ASYNC);
}
else
{
m_hSession = InternetOpen("xihu",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);
}
if( NULL == m_hSession )
{
TRACE( "ERROR: InternetOpen failed \n");
return FALSE;
}
InternetSetStatusCallback(m_hSession,(INTERNET_STATUS_CALLBACK)AsyncInternetCallback);
return TRUE;
}
BOOL CAsyncHttp::AsyncHttpConnect(char* strServerAddr,int nPort)
{
m_hConnect = InternetConnect(m_hSession,strServerAddr,(INTERNET_PORT)nPort,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);
if( NULL == m_hConnect )
{
TRACE( "ERROR: InternetConnect failed \n" );
return FALSE;
}
if (m_bSetProxy)
{
InternetSetOption(m_hConnect,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());
InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_PASSWORD,(LPVOID) m_strProxyUserPass.c_str(),m_strProxyUserPass.length());
}
return TRUE;
}
BOOL CAsyncHttp::AsyncHttpOpenRequest(char* strObjectName,char* strMethod)
{
char* szAccept[] = {"*/*",NULL};
ResetEvent(m_hEventReqOK);
m_hRequest = HttpOpenRequestA(m_hConnect,strMethod,strObjectName,_T("HTTP/1.0"), NULL,(LPCSTR*)szAccept,INTERNET_FLAG_RELOAD,(LPARAM)this);
if( NULL == m_hRequest )
{
if( ERROR_IO_PENDING == GetLastError())
{
if( WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
{
TRACE( "WARMING: HttpOpenRequest failed, maybe timeout \n");
return FALSE;
}
}
else
{
TRACE("ERROR: HttpOpenRequest failed \n");
return FALSE;
}
}
return TRUE;
}
#include <wininet.h>
#pragma comment(lib,"Wininet.lib")
#include <string>
using namespace std;
#define ASYNC_HTTP_OK 0
#define ASYNC_HTTP_ERROR_TIMEOUT -1
#define ASYNC_HTTP_ERROR_CANCEL -2
#define ASYNC_HTTP_ERROR_NET -3
#define ASYNC_HTTP_ERROR_URL -100
#define ASYNC_HTTP_ERROR_CREATE_THREAD -101
#define ASYNC_HTTP_ERR_OTHER -999
#define ASYNC_HTTP_BUFFER_SIZE 4*1024
#define ASYNC_HTTP_RECV_TIMEOUT 1000
class CAsyncHttp
{
public:
CAsyncHttp();
virtual ~CAsyncHttp();
BOOL AsyncHttpOpen();
BOOL AsyncHttpConnect(char* strServerAddr,int nPort);
BOOL AsyncHttpOpenRequest(char* strObjectName,char* strMethod);
BOOL AsyncHttpSetHeader(char* strHeader);
BOOL AsyncHttpSendRequest(char* strBody,int aiLen);
string& AsyncHttpRecieveResponse();
void AsyncHttpCloseConn();
//设置代理
BOOL AsyncHttpSetProxy(string& strProxyServer,long lProxyPort,string& strProxyUser,string& strProxyUserPass);
//取消代理
BOOL AsyncHttpSetProxyOff();
DWORD m_dwErrorCode;
private:
//回调函数,系统api通过该回调函数通知CAsyncHttp http通信过程中的各种状态
static void CALLBACK AsyncInternetCallback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation,DWORD dwStatusInformationLength);
static BOOL WaitAsyncEvent(DWORD dwTimeOut, DWORD dwContext);
void OnDisConnect();
string m_strResponse; //保存返回流
BOOL m_bSetProxy; //确认是否设置了代理
string m_strProxyServer; //代理服务器的地址
long m_lProxyPort; //代理服务器的端口
string m_strProxyUser; //登录代理服务器的用户名
string m_strProxyUserPass; //登录代理服务器的用户密码
HINTERNET m_hSession; //http InternetOpen句柄
HINTERNET m_hConnect; //http InternetConnect句柄
HINTERNET m_hRequest; //http HttpOpenRequestA句柄
HANDLE m_hEventAbort; //用户取消事件句柄
HANDLE m_hEventReqFail; //失败或异常事件句柄
HANDLE m_hEventReqOK; //成功事件句柄
};