#pragma
once
#include < vector >
#include < WinInet.h >
#include " NetDefine.h "
#define T_ACCEPT_ENCODING "Accept-Encoding"
#define T_CLIENTAGENT "Client-Agent"
#define T_CALLINGLINEID "x-up-calling-line-id"
#define T_APIVERSION "APIVersion"
#define T_USERID "user-id"
#define T_ACTION "Action"
#define T_COOKIE "Cookie"
#define T_CONTENTTYPE "Content-Type"
#define T_CLIENTTYPE "X-ClientType"
#define T_CONTENTLEN "Content-Length"
#define T_HOST "Host"
#define T_RESULT_CODE "result-code"
// 一个CHttpSession为一个会话,只负责数据部分
class CHttpSession
{
public :
CHttpSession( CRequestBase & aRequest );
~ CHttpSession();
public :
void SetHWnd( HWND aWnd );
HWND GetHWnd()
{
return m_hWnd;
}
// 在调用Get函数时,需要网络返回完成消息才行
inline const char * GetRecvHead();
// 获取返回的数据体
const char * GetRecvieData( )
{
return m_pRecvBuf;
}
// 获取返回数据的长度
DWORD GetReceivedDataLen()
{
return m_dwRecvBodySize;
}
// 获取返回码
int GetRetCode();
// 获取返回数据头中的字段的值,返回字符串的指针需要自己删除
char * GetRetHeadValue( const char * aKey );
int GetResultCode()
{
char * szResultCode = GetRetHeadValue( T_RESULT_CODE );
if ( ! szResultCode )
{
return - 1 ;
}
int nResultCode = atoi( szResultCode );
FREEARRAYIF( szResultCode );
return nResultCode;
}
EM_RequestID GetRequestID()
{
return m_RequestID ;
}
// aRecvHead在函数内分配空间,调用者必须释放
BOOL RetrievingHeaders(HINTERNET hHttp);
// 重置状态,在发起新的请求之前调用
// void Reset();
const char * GetHost()
{
return m_pHost;
}
int GetPort()
{
return m_pPort;
}
char * GetRequestBody()
{
return m_pRequestBody ;
}
int GetRequestBodyLen()
{
return m_dwRequestBodyLen;
}
const char * GetRequestUrl()
{
return m_pRequestUrl;
}
std::vector < char *>& GetRequestHeadVector()
{
return m_vtRequestHead;
}
protected :
// 返回不包含http: // 和域名的
char * SetRequestUrl( const char * aUrl );
// 添加请求头字符串
bool SetHeadValue( const char * aKey, const char * aValue );
// 设置服务器地址
bool SetServer( const char * aServer );
// 设置端口
bool SetPort( int aPort );
// 设置请求数据,仅用于POST请求,GET请求无需使用
bool SetRequestData( const char * aData );
// 设置请求头
bool SetRequestHead( NetMsgHead * pHead );
public :
HANDLE m_hThread; // 下载子线程句柄
DWORD m_dwThreadID; // 线程ID
HINTERNET hInstance;
HINTERNET hConnect;
HINTERNET hRequest;
HANDLE hEvent[ 3 ]; // 0:句柄被创建事件或者读数据请求成功完成事件,1: // 句柄被关闭事件,2:用户要求终止子线程事件或者发生错误事件
char * m_pRecvHead; // 接收到的数据头
char * m_pRecvBuf; // 接收的缓存
DWORD m_dwRecvBodySize; // 收到数据的总大小
DWORD m_dwMaxBuf; // 接收数据缓存的总容器大小
DWORD m_dwStartPos; // 当前缓存的偏移,已存放在缓存中的数据长度
protected :
std::vector < char *> m_vtRequestHead; // 请求消息头的字符串
char * m_pRequestBody; // 请求的消息体
DWORD m_dwRequestBodyLen; // 请求消息体的长度
char * m_pHost; // 服务器地址
int m_pPort; // 端口
char * m_pRequestUrl; // 请求URL地址
HWND m_hWnd; // 用于接收网络通知的窗口句柄
EM_RequestID m_RequestID; // 保留当前网络会话ID
};
class CAsyncWinINet
{
public :
static DWORD download( CHttpSession & aHttpSession );
protected :
static BOOL WaitExitEvent(CHttpSession * p);
static DWORD WINAPI AsyncThread(LPVOID lpParameter);
static VOID CALLBACK AsyncInternetCallback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
};
#include < vector >
#include < WinInet.h >
#include " NetDefine.h "
#define T_ACCEPT_ENCODING "Accept-Encoding"
#define T_CLIENTAGENT "Client-Agent"
#define T_CALLINGLINEID "x-up-calling-line-id"
#define T_APIVERSION "APIVersion"
#define T_USERID "user-id"
#define T_ACTION "Action"
#define T_COOKIE "Cookie"
#define T_CONTENTTYPE "Content-Type"
#define T_CLIENTTYPE "X-ClientType"
#define T_CONTENTLEN "Content-Length"
#define T_HOST "Host"
#define T_RESULT_CODE "result-code"
// 一个CHttpSession为一个会话,只负责数据部分
class CHttpSession
{
public :
CHttpSession( CRequestBase & aRequest );
~ CHttpSession();
public :
void SetHWnd( HWND aWnd );
HWND GetHWnd()
{
return m_hWnd;
}
// 在调用Get函数时,需要网络返回完成消息才行
inline const char * GetRecvHead();
// 获取返回的数据体
const char * GetRecvieData( )
{
return m_pRecvBuf;
}
// 获取返回数据的长度
DWORD GetReceivedDataLen()
{
return m_dwRecvBodySize;
}
// 获取返回码
int GetRetCode();
// 获取返回数据头中的字段的值,返回字符串的指针需要自己删除
char * GetRetHeadValue( const char * aKey );
int GetResultCode()
{
char * szResultCode = GetRetHeadValue( T_RESULT_CODE );
if ( ! szResultCode )
{
return - 1 ;
}
int nResultCode = atoi( szResultCode );
FREEARRAYIF( szResultCode );
return nResultCode;
}
EM_RequestID GetRequestID()
{
return m_RequestID ;
}
// aRecvHead在函数内分配空间,调用者必须释放
BOOL RetrievingHeaders(HINTERNET hHttp);
// 重置状态,在发起新的请求之前调用
// void Reset();
const char * GetHost()
{
return m_pHost;
}
int GetPort()
{
return m_pPort;
}
char * GetRequestBody()
{
return m_pRequestBody ;
}
int GetRequestBodyLen()
{
return m_dwRequestBodyLen;
}
const char * GetRequestUrl()
{
return m_pRequestUrl;
}
std::vector < char *>& GetRequestHeadVector()
{
return m_vtRequestHead;
}
protected :
// 返回不包含http: // 和域名的
char * SetRequestUrl( const char * aUrl );
// 添加请求头字符串
bool SetHeadValue( const char * aKey, const char * aValue );
// 设置服务器地址
bool SetServer( const char * aServer );
// 设置端口
bool SetPort( int aPort );
// 设置请求数据,仅用于POST请求,GET请求无需使用
bool SetRequestData( const char * aData );
// 设置请求头
bool SetRequestHead( NetMsgHead * pHead );
public :
HANDLE m_hThread; // 下载子线程句柄
DWORD m_dwThreadID; // 线程ID
HINTERNET hInstance;
HINTERNET hConnect;
HINTERNET hRequest;
HANDLE hEvent[ 3 ]; // 0:句柄被创建事件或者读数据请求成功完成事件,1: // 句柄被关闭事件,2:用户要求终止子线程事件或者发生错误事件
char * m_pRecvHead; // 接收到的数据头
char * m_pRecvBuf; // 接收的缓存
DWORD m_dwRecvBodySize; // 收到数据的总大小
DWORD m_dwMaxBuf; // 接收数据缓存的总容器大小
DWORD m_dwStartPos; // 当前缓存的偏移,已存放在缓存中的数据长度
protected :
std::vector < char *> m_vtRequestHead; // 请求消息头的字符串
char * m_pRequestBody; // 请求的消息体
DWORD m_dwRequestBodyLen; // 请求消息体的长度
char * m_pHost; // 服务器地址
int m_pPort; // 端口
char * m_pRequestUrl; // 请求URL地址
HWND m_hWnd; // 用于接收网络通知的窗口句柄
EM_RequestID m_RequestID; // 保留当前网络会话ID
};
class CAsyncWinINet
{
public :
static DWORD download( CHttpSession & aHttpSession );
protected :
static BOOL WaitExitEvent(CHttpSession * p);
static DWORD WINAPI AsyncThread(LPVOID lpParameter);
static VOID CALLBACK AsyncInternetCallback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
};
#include
"
stdafx.h
"
#include " HttpSession.h "
#include " Util.h "
#pragma comment(lib, "Wininet.lib")
HWND g_hWnd ;
#define CONNECTION_CONTEXT 1
#define REQUEST_CONTEXT 2
#define MAX_BODY_SIZE 10*1024
#define RECV_STEP 1024
DWORD CAsyncWinINet::download( CHttpSession & aHttpSession )
{
aHttpSession.m_hThread = CreateThread(NULL,
0 ,
CAsyncWinINet::AsyncThread,
& aHttpSession,
NULL,
& aHttpSession.m_dwThreadID);
if ( aHttpSession.m_hThread )
{
TraceLog( L " Create DownloadThread sucess, ThreadHandle = %d!\r\n " , aHttpSession.m_dwThreadID );
}
// 等待子线程安全退出
WaitForSingleObject(aHttpSession.m_hThread, INFINITE);
TraceLog( L " download Thread:%d exit!\r\n " ,aHttpSession.m_dwThreadID );
// 关闭线程句柄
CloseHandle(aHttpSession.m_hThread);
return TRUE;
}
DWORD WINAPI CAsyncWinINet::AsyncThread(LPVOID lpParameter)
{
CHttpSession * pSession = (CHttpSession * )lpParameter;
pSession -> hInstance = InternetOpenA( ""
,INTERNET_OPEN_TYPE_PRECONFIG
,NULL
,NULL
,INTERNET_FLAG_ASYNC);
if ( ! pSession -> hInstance ) // 有些手机用上面的参数访问不了Internet
pSession -> hInstance = InternetOpenA( ""
,INTERNET_OPEN_TYPE_DIRECT
,NULL
,NULL
,INTERNET_FLAG_ASYNC);
if ( ! pSession -> hInstance )
{
TraceLog( L " InternetOpen failed, error : %d \r\n " ,GetLastError() );
return false ;
}
TraceLog( L " InternetOpen suceess !\r\n " );
// Setup callback function
// ResetEvent(p->hEvent[0]);
// p->hCallbackThread = CreateThread(NULL,
// 0,
// AsyncWinINet::AsyncCallbackThread,
// p,
// NULL,
// &p->dwCallbackThreadID);
// WaitForSingleObject(p->hEvent[0], INFINITE); // 等待回调函数设置成功事件
if ( InternetSetStatusCallbackA( pSession -> hInstance,CAsyncWinINet::AsyncInternetCallback )
== INTERNET_INVALID_STATUS_CALLBACK )
{
TraceLog( L " InternetSetStatusCallback failed, error : %d \r\n " ,GetLastError() );
return false ;
}
TraceLog( L " InternetSetStatusCallback suceess :%d \r\n " ,GetLastError() );
// First call that will actually complete asynchronously even though there is no network traffic
pSession -> hConnect = InternetConnectA( pSession -> hInstance
,pSession -> GetHost()
,pSession -> GetPort()
,NULL
,NULL
,INTERNET_SERVICE_HTTP
, 0
,(DWORD)pSession); // Connection handle's Context
if ( ! pSession -> hConnect )
{
TraceLog( L " hConnect == NULL, errno = %d \r\n " ,GetLastError() );
if (GetLastError() != ERROR_IO_PENDING)
{
// TODO:退出线程
return false ;
}
}
// Wait until we get the connection handle
// WaitForSingleObject( pSession->hEvent[0], INFINITE);
TraceLog( L " Ready To openRequest \r\n " );
char * pRequestBody = pSession -> GetRequestBody();
char * pVerb = ! pRequestBody ? " GET " : " POST " ;
// Open the request
ResetEvent( pSession -> hEvent[ 0 ] );
pSession -> hRequest = HttpOpenRequestA(pSession -> hConnect
,pVerb
,pSession -> GetRequestUrl()
,NULL // HTTP version ,If this parameter is NULL, the function uses HTTP/1.1 as the version
,NULL // Reference
,NULL // A pointer to a null-terminated array of strings that indicates media types accepted by the client.
,INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE
,(DWORD)pSession); // Request handle's context
// Wait until we get the request handle
// WaitForSingleObject( pSession->hEvent[0], INFINITE );
TraceLog( L " HttpOpenRequest Sucess\r\n " );
// Add Request HeadInfo
std::vector < char *> vtHead = pSession -> GetRequestHeadVector();
for ( unsigned int i = 0 ; i < vtHead.size(); i ++ )
{
char * pItem = vtHead[i];
HttpAddRequestHeadersA(pSession -> hRequest, pItem, - 1 , HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE );
}
int nRequestBodyLen = pSession -> GetRequestBodyLen();
// Sends the specified request to the HTTP server.
// ResetEvent( pSession->hEvent[0] );
if ( ! HttpSendRequestA( pSession -> hRequest
,NULL // Pointer to a null-terminated string that contains the additional headers to be appended to the request.
, 0 // Size of the additional headers
,pRequestBody // Pointer to a buffer containing any optional data to be sent immediately after the request headers.
,nRequestBodyLen )) // Size of the optional data, in bytes.
{
if (GetLastError() != ERROR_IO_PENDING)
{
TraceLog( L " HttpSendRequest failed, error = %d \r\n " , GetLastError() );
return false ;
}
}
TraceLog( L " HttpSendRequest Sucess \r\n " );
WaitForSingleObject( pSession -> hEvent[ 0 ], INFINITE );
// receive Head
pSession -> RetrievingHeaders( pSession -> hRequest );
// 网络错误处理:返回0为正常,非0为错误
int nResultCode = pSession -> GetResultCode();
if ( nResultCode > 0 )
{
PostMessage(pSession -> GetHWnd(), Event_NetError, nResultCode, NULL );
}
else
{
char lpReadBuff[RECV_STEP] ;
DWORD dwStartPos = 0 ;
while ( true )
{
memset(lpReadBuff, 0 , RECV_STEP);
INTERNET_BUFFERSA InetBuff;
FillMemory( & InetBuff, sizeof (InetBuff), 0 );
InetBuff.dwStructSize = sizeof (InetBuff);
InetBuff.lpvBuffer = (LPVOID)lpReadBuff;
InetBuff.dwBufferLength = RECV_STEP;
TraceLog( L " Calling InternetReadFileExA \r\n " );
ResetEvent( pSession -> hEvent[ 0 ] );
if ( ! InternetReadFileExA(pSession -> hRequest, & InetBuff,IRF_ASYNC, (DWORD)pSession) )
{
if (GetLastError() == ERROR_IO_PENDING)
{
TraceLog( L " Waiting for InternetReadFileEx to complete \r\n " );
if (WaitExitEvent(pSession)) break ;
// WaitForSingleObject(pSession->hRequestCompleteEvent, INFINITE);
}
else
{
TraceLog( L " InternetReadFileEx failed, error :%d \r\n " , GetLastError() );
return false ;
}
}
else
{
// 在网络传输速度快,步长较小的情况下,InternetReadFileEx 经常会直接返回成功,
// 因此要判断是否发生了用户要求终止子线程事件。
if (WAIT_OBJECT_0 == WaitForSingleObject(pSession -> hEvent[ 2 ], 0 ))
{
ResetEvent(pSession -> hEvent[ 2 ]);
break ;
}
}
TraceLog( L " InternetReadFileEx success! ReadBufLen = %d \r\n " , InetBuff.dwBufferLength );
if (InetBuff.dwBufferLength == 0 )
{
// TraceLog( L"RecvBuf Complete \r\n");
// bAllDone = TRUE;
// FILE *file;
// file = fopen( "\\a1.jpg", "wb" );
// int nwrite;
// if ( file )
// {
// nwrite = fwrite( m_pRecvBuf, 1, m_dwRecvBodySize, file);
// }
// fclose(file);
// Reset();
PostMessage(pSession -> GetHWnd(), Event_NetState, INTERNET_STATUS_REQUEST_COMPLETE, NULL );
break ; // 接收数据完成,跳出循环
}
else
{
pSession -> m_dwRecvBodySize += InetBuff.dwBufferLength;
if ( ! pSession -> m_pRecvBuf )
{
pSession -> m_pRecvBuf = new char [MAX_BODY_SIZE];
memset( pSession -> m_pRecvBuf, 0 , MAX_BODY_SIZE );
pSession -> m_dwMaxBuf = MAX_BODY_SIZE;
}
// 剩余空间不足,重新分配空间
if ( pSession -> m_dwMaxBuf - dwStartPos < InetBuff.dwBufferLength + 1 )
{
TraceLog( L " Memspace is not enough! " );
char * pTempBuf = pSession -> m_pRecvBuf;
pSession -> m_pRecvBuf = new char [pSession -> m_dwMaxBuf + MAX_BODY_SIZE];
memset( pSession -> m_pRecvBuf, 0 , pSession -> m_dwMaxBuf + MAX_BODY_SIZE);
pSession -> m_dwMaxBuf += MAX_BODY_SIZE;
memcpy( pSession -> m_pRecvBuf, pTempBuf, dwStartPos);
delete[] pTempBuf;
pTempBuf = NULL;
}
TraceLog( L " Memspace is enough! " );
memcpy( pSession -> m_pRecvBuf + dwStartPos, lpReadBuff, InetBuff.dwBufferLength );
TraceLog( L " InternetReadFileEx startPos = %d, curRecvLen = %d, totalSize = %d! \r\n " , dwStartPos, InetBuff.dwBufferLength , pSession -> m_dwRecvBodySize);
dwStartPos += InetBuff.dwBufferLength;
}
}
}
if ( pSession -> hRequest )
{
InternetCloseHandle( pSession -> hRequest ); // 关闭 m_hFile
while ( ! WaitExitEvent( pSession )) // 等待句柄被关闭事件或者要求子线程退出事件
{
ResetEvent( pSession -> hEvent[ 0 ] );
}
}
// 清理资源,结束子进程
// 设置子线程退出事件,通知回调线程退出
SetEvent( pSession -> hEvent[ 2 ] );
// 注销回调函数
InternetSetStatusCallback( pSession -> hInstance, NULL);
InternetCloseHandle( pSession -> hInstance );
return TRUE;
}
BOOL CAsyncWinINet::WaitExitEvent(CHttpSession * aSession)
{
DWORD dwRet = WaitForMultipleObjects( 3 , aSession -> hEvent, FALSE, INFINITE);
switch (dwRet)
{
case WAIT_OBJECT_0: // 句柄被创建事件或者读数据请求成功完成事件
case WAIT_OBJECT_0 + 1 : // 句柄被关闭事件
case WAIT_OBJECT_0 + 2 : // 用户要求终止子线程事件或者发生错误事件
break ;
}
return WAIT_OBJECT_0 != dwRet;
}
VOID CALLBACK CAsyncWinINet::AsyncInternetCallback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
CHttpSession * pSession = (CHttpSession * )dwContext;
// 在我们的应用中,我们只关心下面三个状态
switch (dwInternetStatus)
{
// 句柄被创建
case INTERNET_STATUS_HANDLE_CREATED:
{
INTERNET_ASYNC_RESULT * pRes = (INTERNET_ASYNC_RESULT * )lpvStatusInformation;
pSession -> hConnect = (HINTERNET)pRes -> dwResult;
TraceLog( L " Connect handle created \r\n " );
SetEvent( pSession -> hConnect );
break ;
}
// 句柄被关闭
case INTERNET_STATUS_HANDLE_CLOSING:
SetEvent( pSession -> hEvent[ 1 ] );
break ;
// 一个请求完成,比如一次句柄创建的请求,或者一次读数据的请求
case INTERNET_STATUS_REQUEST_COMPLETE:
if (ERROR_SUCCESS == ((LPINTERNET_ASYNC_RESULT)
(lpvStatusInformation)) -> dwError)
{
// 设置句柄被创建事件或者读数据成功完成事件
SetEvent( pSession -> hEvent[ 0 ] );
}
else
{
// 如果发生错误,则设置子线程退出事件 这里也是一个陷阱,经常会忽视处理这个错误,
SetEvent( pSession -> hEvent[ 2 ] );
}
break ;
case INTERNET_STATUS_CONNECTION_CLOSED:
SetEvent( pSession -> hEvent[ 2 ] );
break ;
}
};
CHttpSession::CHttpSession( CRequestBase & aRequest )
:m_pRequestBody(NULL),m_pHost(NULL), m_pRequestUrl( NULL ),m_pRecvBuf(NULL),m_pRecvHead(NULL)
,m_dwRecvBodySize( 0 ), m_dwMaxBuf( 0 ) ,m_dwStartPos( 0 ),m_dwRequestBodyLen( 0 ), m_hWnd( 0 ),m_RequestID(EM_Req_Start)
,m_dwThreadID( 0 ),m_hThread( 0 )
{
m_vtRequestHead.clear();
for ( int i = 0 ; i < 3 ; ++ i)
{
hEvent[i] = CreateEvent(NULL,TRUE,FALSE,NULL);
}
NetMsgHead * pHead = aRequest.GetRequestHead();
if ( ! SetRequestHead(pHead) )
return ;
const char * pHost = pHead -> GetHost();
SetServer( pHost );
int port = pHead -> GetPort();
SetPort( port );
const char * pRequestURL = aRequest.GetUrl();
m_pRequestUrl = SetRequestUrl( pRequestURL );
m_RequestID = aRequest.GetRequestID();
bool bPost = aRequest.GetIsPostMsg();
if ( bPost )
{
const char * pData = (( CPostRsqBase * ) & aRequest) -> GetRequestBody();
SetRequestData( pData );
}
else
{
SetRequestData( NULL );
}
}
CHttpSession:: ~ CHttpSession()
{
FREEARRAYIF( m_pRequestBody );
FREEARRAYIF( m_pHost );
FREEARRAYIF( m_pRequestUrl );
FREEARRAYIF( m_pRecvBuf );
FREEARRAYIF( m_pRecvHead );
if (hConnect)
{
InternetCloseHandle(hConnect);
hConnect = NULL;
}
if (hInstance)
{
// 卸载回调
InternetSetStatusCallback(hInstance,NULL);
InternetCloseHandle(hInstance);
hInstance = NULL;
}
if (hRequest)
{
InternetCloseHandle(hRequest);
hRequest = NULL;
}
for ( int i = 0 ; i < 3 ; i ++ )
{
if ( hEvent[i] )
{
CloseHandle(hEvent[i]);
hEvent[i] = NULL;
}
}
}
// void CHttpSession::Reset()
// {
// FREEARRAYIF( m_pRequestBody );
// FREEARRAYIF( m_pHost );
// FREEARRAYIF( m_pRequestUrl );
// FREEARRAYIF( m_pRecvBuf );
// FREEARRAYIF( m_pRecvHead );
//
// m_dwRecvBodySize = 0;
// m_dwMaxBuf = 0;
// m_dwStartPos = 0;
// m_dwRequestBodyLen = 0;
// m_RequestID = EM_Req_Start;
// m_pPort = 0;
//
// if(hConnect)
// {
// InternetCloseHandle(hConnect);
// hConnect = NULL;
// }
//
// if(hInstance)
// {
// // 卸载回调
// InternetSetStatusCallback(hInstance,NULL);
// InternetCloseHandle(hInstance);
// hInstance=NULL;
// }
//
// if(hRequest)
// {
// InternetCloseHandle(hRequest);
// hRequest = NULL;
// }
//
// for ( int i = 0 ; i < 3; i++ )
// {
// if ( hEvent[i] )
// {
// CloseHandle(hEvent[i]);
// hEvent[i] = NULL;
// }
// }
//
// // if(hRequestCompleteEvent)
// // {
// // CloseHandle(hRequestCompleteEvent);
// // hRequestCompleteEvent = NULL;
// // }
// //
// // if(hConnectedEvent)
// // {
// // CloseHandle(hConnectedEvent);
// // hConnectedEvent = NULL;
// // }
// //
// // if(hRequestOpenedEvent)
// // {
// // CloseHandle(hRequestOpenedEvent);
// // hRequestOpenedEvent = NULL;
// // }
//
// for ( unsigned int i = 0 ; i < m_vtRequestHead.size(); i++ )
// {
// char* pItem = m_vtRequestHead[i];
// FREEARRAYIF( pItem );
// }
// m_vtRequestHead.clear();
// }
//
void CHttpSession::SetHWnd( HWND aWnd )
{
m_hWnd = aWnd;
g_hWnd = aWnd;
}
bool CHttpSession::SetHeadValue( const char * aKey, const char * aValue )
{
if ( ! aKey )
return false ;
char * buf = new char [ 256 ];
memset( buf, 0 , 256 );
sprintf( buf, " %s: %s\r\n " , aKey, aValue );
m_vtRequestHead.push_back( buf );
return true ;
}
bool CHttpSession::SetRequestData( const char * aData )
{
if ( ! aData )
return false ;
m_pRequestBody = new char [strlen( aData ) + 1 ];
memset( m_pRequestBody, 0 , strlen( aData ) + 1 );
memcpy( m_pRequestBody, aData, strlen( aData ) );
m_dwRequestBodyLen = strlen( aData );
return true ;
}
bool CHttpSession::SetServer( const char * aServer )
{
if ( ! aServer )
return false ;
m_pHost = new char [strlen( aServer ) + 1 ];
memset( m_pHost, 0 , strlen( aServer ) + 1 );
memcpy( m_pHost, aServer, strlen( aServer ) );
return true ;
}
char * CHttpSession::SetRequestUrl( const char * aUrl )
{
if ( ! aUrl )
return false ;
const char * pUrl = aUrl;
// 检查是否存在http: //
const char * pUrlHead = " http:// " ;
char * pTemp = strstr( pUrl, pUrlHead );
char * pResult = NULL;
// 在开始处
if ( pTemp )
{
if ( pTemp == pUrl )
{
pTemp += strlen( pUrlHead );
// 查找第一个 "/",去掉域名
pTemp = strstr( pTemp, " / " );
if ( ! pTemp )
{
return NULL;
}
pResult = new char [ strlen( pTemp ) + 1 ] ;
memset( pResult, 0 , strlen( pTemp ) + 1 );
memcpy( pResult, pTemp, strlen( pTemp ) );
return pResult;
}
}
else
{
// 没有找到
pResult = new char [ strlen( pUrl ) + 1 ] ;
memset( pResult, 0 , strlen( pUrl ) + 1 );
memcpy( pResult, pUrl, strlen( pUrl ) );
return pResult;
}
return pResult;
}
bool CHttpSession::SetPort( int aPort )
{
if ( aPort < 0 )
{
return false ;
}
m_pPort = aPort;
return true ;
}
bool CHttpSession::SetRequestHead( NetMsgHead * pHead )
{
if ( ! pHead )
return false ;
const char * pszBuf = pHead -> GetAcceptEncoding();
SetHeadValue( T_ACCEPT_ENCODING, pszBuf );
pszBuf = pHead -> GetClientAgent();
SetHeadValue( T_CLIENTAGENT, pszBuf );
pszBuf = pHead -> GetCallingLineID();
SetHeadValue( T_CALLINGLINEID, pszBuf );
pszBuf = pHead -> GetApiVersion();
SetHeadValue( T_APIVERSION, pszBuf );
pszBuf = pHead -> GetContentType();
SetHeadValue( T_CONTENTTYPE, pszBuf );
pszBuf = pHead -> GetXClientType();
SetHeadValue( T_CLIENTTYPE, pszBuf );
pszBuf = pHead -> GetUserid();
SetHeadValue( T_USERID, pszBuf );
pszBuf = pHead -> GetCookie();
SetHeadValue( T_COOKIE, pszBuf );
pszBuf = pHead -> GetAction();
SetHeadValue( T_ACTION, pszBuf );
return true ;
}
BOOL CHttpSession::RetrievingHeaders( HINTERNET hHttp )
{
// LPVOID lpOutBuffer=NULL;
DWORD dwSize = 0 ;
retry:
// This call will fail on the first pass, because no buffer is allocated.
if ( ! HttpQueryInfoA(
hHttp,
HTTP_QUERY_RAW_HEADERS_CRLF,
(LPVOID)m_pRecvHead,
& dwSize,
NULL))
{
if (GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND)
{
TraceLog( L " HttpQueryInfo error : ERROR_HTTP_HEADER_NOT_FOUND \r\n " );
// Code to handle the case where the header isn't available.
return TRUE;
}
else
{
// Check for an insufficient buffer.
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
{
TraceLog( L " HttpQueryInfo error : ERROR_HTTP_HEADER_NOT_FOUND \r\n " );
m_pRecvHead = new char [dwSize];
// Retry the call.
goto retry;
}
else
{
TraceLog( L " HttpQueryInfo error : %d \r\n " , GetLastError() );
// Error handling code.
if (m_pRecvHead)
{
delete [] m_pRecvHead;
}
return FALSE;
}
}
}
TraceLog( L " HttpQueryInfo sucess lpOutBuffer = %s\r\n " , m_pRecvHead );
return TRUE;
}
int CHttpSession::GetRetCode()
{
if ( ! m_pRecvHead )
{
return - 1 ;
}
// 寻找第一个空格
char * pRet1 = strstr( m_pRecvHead, " " );
if ( ! pRet1 )
{
return - 1 ;
}
char * pStart = pRet1 + 1 ;
char * pRet2 = strstr( pStart, " " );
if ( ! pRet2 )
{
return - 1 ;
}
int nLen = pRet2 - pStart;
char * pRetCode = new char [nLen + 1 ];
memset( pRetCode, 0 , nLen + 1 );
memcpy( pRetCode, pStart, nLen );
int nRet = atoi( pRetCode );
FREEARRAYIF( pRetCode );
return nRet;
}
char * CHttpSession::GetRetHeadValue( const char * aKey )
{
if ( ! m_pRecvHead )
{
return NULL;
}
// 寻找key
char * pResult1 = strstr( m_pRecvHead, aKey );
if ( ! pResult1 )
{
return NULL;
}
pResult1 = strstr( pResult1, " : " );
if ( ! pResult1 )
{
return NULL;
}
pResult1 += strlen( " : " );
char * pResult2 = strstr( pResult1, " \r\n " );
int nValueLen = pResult2 - pResult1 ;
char * pRet = new char [nValueLen + 1 ];
memset( pRet, 0 , nValueLen + 1 );
memcpy( pRet, pResult1, nValueLen );
return pRet;
}
const char * CHttpSession::GetRecvHead()
{
return m_pRecvHead;
}
#include " HttpSession.h "
#include " Util.h "
#pragma comment(lib, "Wininet.lib")
HWND g_hWnd ;
#define CONNECTION_CONTEXT 1
#define REQUEST_CONTEXT 2
#define MAX_BODY_SIZE 10*1024
#define RECV_STEP 1024
DWORD CAsyncWinINet::download( CHttpSession & aHttpSession )
{
aHttpSession.m_hThread = CreateThread(NULL,
0 ,
CAsyncWinINet::AsyncThread,
& aHttpSession,
NULL,
& aHttpSession.m_dwThreadID);
if ( aHttpSession.m_hThread )
{
TraceLog( L " Create DownloadThread sucess, ThreadHandle = %d!\r\n " , aHttpSession.m_dwThreadID );
}
// 等待子线程安全退出
WaitForSingleObject(aHttpSession.m_hThread, INFINITE);
TraceLog( L " download Thread:%d exit!\r\n " ,aHttpSession.m_dwThreadID );
// 关闭线程句柄
CloseHandle(aHttpSession.m_hThread);
return TRUE;
}
DWORD WINAPI CAsyncWinINet::AsyncThread(LPVOID lpParameter)
{
CHttpSession * pSession = (CHttpSession * )lpParameter;
pSession -> hInstance = InternetOpenA( ""
,INTERNET_OPEN_TYPE_PRECONFIG
,NULL
,NULL
,INTERNET_FLAG_ASYNC);
if ( ! pSession -> hInstance ) // 有些手机用上面的参数访问不了Internet
pSession -> hInstance = InternetOpenA( ""
,INTERNET_OPEN_TYPE_DIRECT
,NULL
,NULL
,INTERNET_FLAG_ASYNC);
if ( ! pSession -> hInstance )
{
TraceLog( L " InternetOpen failed, error : %d \r\n " ,GetLastError() );
return false ;
}
TraceLog( L " InternetOpen suceess !\r\n " );
// Setup callback function
// ResetEvent(p->hEvent[0]);
// p->hCallbackThread = CreateThread(NULL,
// 0,
// AsyncWinINet::AsyncCallbackThread,
// p,
// NULL,
// &p->dwCallbackThreadID);
// WaitForSingleObject(p->hEvent[0], INFINITE); // 等待回调函数设置成功事件
if ( InternetSetStatusCallbackA( pSession -> hInstance,CAsyncWinINet::AsyncInternetCallback )
== INTERNET_INVALID_STATUS_CALLBACK )
{
TraceLog( L " InternetSetStatusCallback failed, error : %d \r\n " ,GetLastError() );
return false ;
}
TraceLog( L " InternetSetStatusCallback suceess :%d \r\n " ,GetLastError() );
// First call that will actually complete asynchronously even though there is no network traffic
pSession -> hConnect = InternetConnectA( pSession -> hInstance
,pSession -> GetHost()
,pSession -> GetPort()
,NULL
,NULL
,INTERNET_SERVICE_HTTP
, 0
,(DWORD)pSession); // Connection handle's Context
if ( ! pSession -> hConnect )
{
TraceLog( L " hConnect == NULL, errno = %d \r\n " ,GetLastError() );
if (GetLastError() != ERROR_IO_PENDING)
{
// TODO:退出线程
return false ;
}
}
// Wait until we get the connection handle
// WaitForSingleObject( pSession->hEvent[0], INFINITE);
TraceLog( L " Ready To openRequest \r\n " );
char * pRequestBody = pSession -> GetRequestBody();
char * pVerb = ! pRequestBody ? " GET " : " POST " ;
// Open the request
ResetEvent( pSession -> hEvent[ 0 ] );
pSession -> hRequest = HttpOpenRequestA(pSession -> hConnect
,pVerb
,pSession -> GetRequestUrl()
,NULL // HTTP version ,If this parameter is NULL, the function uses HTTP/1.1 as the version
,NULL // Reference
,NULL // A pointer to a null-terminated array of strings that indicates media types accepted by the client.
,INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE
,(DWORD)pSession); // Request handle's context
// Wait until we get the request handle
// WaitForSingleObject( pSession->hEvent[0], INFINITE );
TraceLog( L " HttpOpenRequest Sucess\r\n " );
// Add Request HeadInfo
std::vector < char *> vtHead = pSession -> GetRequestHeadVector();
for ( unsigned int i = 0 ; i < vtHead.size(); i ++ )
{
char * pItem = vtHead[i];
HttpAddRequestHeadersA(pSession -> hRequest, pItem, - 1 , HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE );
}
int nRequestBodyLen = pSession -> GetRequestBodyLen();
// Sends the specified request to the HTTP server.
// ResetEvent( pSession->hEvent[0] );
if ( ! HttpSendRequestA( pSession -> hRequest
,NULL // Pointer to a null-terminated string that contains the additional headers to be appended to the request.
, 0 // Size of the additional headers
,pRequestBody // Pointer to a buffer containing any optional data to be sent immediately after the request headers.
,nRequestBodyLen )) // Size of the optional data, in bytes.
{
if (GetLastError() != ERROR_IO_PENDING)
{
TraceLog( L " HttpSendRequest failed, error = %d \r\n " , GetLastError() );
return false ;
}
}
TraceLog( L " HttpSendRequest Sucess \r\n " );
WaitForSingleObject( pSession -> hEvent[ 0 ], INFINITE );
// receive Head
pSession -> RetrievingHeaders( pSession -> hRequest );
// 网络错误处理:返回0为正常,非0为错误
int nResultCode = pSession -> GetResultCode();
if ( nResultCode > 0 )
{
PostMessage(pSession -> GetHWnd(), Event_NetError, nResultCode, NULL );
}
else
{
char lpReadBuff[RECV_STEP] ;
DWORD dwStartPos = 0 ;
while ( true )
{
memset(lpReadBuff, 0 , RECV_STEP);
INTERNET_BUFFERSA InetBuff;
FillMemory( & InetBuff, sizeof (InetBuff), 0 );
InetBuff.dwStructSize = sizeof (InetBuff);
InetBuff.lpvBuffer = (LPVOID)lpReadBuff;
InetBuff.dwBufferLength = RECV_STEP;
TraceLog( L " Calling InternetReadFileExA \r\n " );
ResetEvent( pSession -> hEvent[ 0 ] );
if ( ! InternetReadFileExA(pSession -> hRequest, & InetBuff,IRF_ASYNC, (DWORD)pSession) )
{
if (GetLastError() == ERROR_IO_PENDING)
{
TraceLog( L " Waiting for InternetReadFileEx to complete \r\n " );
if (WaitExitEvent(pSession)) break ;
// WaitForSingleObject(pSession->hRequestCompleteEvent, INFINITE);
}
else
{
TraceLog( L " InternetReadFileEx failed, error :%d \r\n " , GetLastError() );
return false ;
}
}
else
{
// 在网络传输速度快,步长较小的情况下,InternetReadFileEx 经常会直接返回成功,
// 因此要判断是否发生了用户要求终止子线程事件。
if (WAIT_OBJECT_0 == WaitForSingleObject(pSession -> hEvent[ 2 ], 0 ))
{
ResetEvent(pSession -> hEvent[ 2 ]);
break ;
}
}
TraceLog( L " InternetReadFileEx success! ReadBufLen = %d \r\n " , InetBuff.dwBufferLength );
if (InetBuff.dwBufferLength == 0 )
{
// TraceLog( L"RecvBuf Complete \r\n");
// bAllDone = TRUE;
// FILE *file;
// file = fopen( "\\a1.jpg", "wb" );
// int nwrite;
// if ( file )
// {
// nwrite = fwrite( m_pRecvBuf, 1, m_dwRecvBodySize, file);
// }
// fclose(file);
// Reset();
PostMessage(pSession -> GetHWnd(), Event_NetState, INTERNET_STATUS_REQUEST_COMPLETE, NULL );
break ; // 接收数据完成,跳出循环
}
else
{
pSession -> m_dwRecvBodySize += InetBuff.dwBufferLength;
if ( ! pSession -> m_pRecvBuf )
{
pSession -> m_pRecvBuf = new char [MAX_BODY_SIZE];
memset( pSession -> m_pRecvBuf, 0 , MAX_BODY_SIZE );
pSession -> m_dwMaxBuf = MAX_BODY_SIZE;
}
// 剩余空间不足,重新分配空间
if ( pSession -> m_dwMaxBuf - dwStartPos < InetBuff.dwBufferLength + 1 )
{
TraceLog( L " Memspace is not enough! " );
char * pTempBuf = pSession -> m_pRecvBuf;
pSession -> m_pRecvBuf = new char [pSession -> m_dwMaxBuf + MAX_BODY_SIZE];
memset( pSession -> m_pRecvBuf, 0 , pSession -> m_dwMaxBuf + MAX_BODY_SIZE);
pSession -> m_dwMaxBuf += MAX_BODY_SIZE;
memcpy( pSession -> m_pRecvBuf, pTempBuf, dwStartPos);
delete[] pTempBuf;
pTempBuf = NULL;
}
TraceLog( L " Memspace is enough! " );
memcpy( pSession -> m_pRecvBuf + dwStartPos, lpReadBuff, InetBuff.dwBufferLength );
TraceLog( L " InternetReadFileEx startPos = %d, curRecvLen = %d, totalSize = %d! \r\n " , dwStartPos, InetBuff.dwBufferLength , pSession -> m_dwRecvBodySize);
dwStartPos += InetBuff.dwBufferLength;
}
}
}
if ( pSession -> hRequest )
{
InternetCloseHandle( pSession -> hRequest ); // 关闭 m_hFile
while ( ! WaitExitEvent( pSession )) // 等待句柄被关闭事件或者要求子线程退出事件
{
ResetEvent( pSession -> hEvent[ 0 ] );
}
}
// 清理资源,结束子进程
// 设置子线程退出事件,通知回调线程退出
SetEvent( pSession -> hEvent[ 2 ] );
// 注销回调函数
InternetSetStatusCallback( pSession -> hInstance, NULL);
InternetCloseHandle( pSession -> hInstance );
return TRUE;
}
BOOL CAsyncWinINet::WaitExitEvent(CHttpSession * aSession)
{
DWORD dwRet = WaitForMultipleObjects( 3 , aSession -> hEvent, FALSE, INFINITE);
switch (dwRet)
{
case WAIT_OBJECT_0: // 句柄被创建事件或者读数据请求成功完成事件
case WAIT_OBJECT_0 + 1 : // 句柄被关闭事件
case WAIT_OBJECT_0 + 2 : // 用户要求终止子线程事件或者发生错误事件
break ;
}
return WAIT_OBJECT_0 != dwRet;
}
VOID CALLBACK CAsyncWinINet::AsyncInternetCallback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
CHttpSession * pSession = (CHttpSession * )dwContext;
// 在我们的应用中,我们只关心下面三个状态
switch (dwInternetStatus)
{
// 句柄被创建
case INTERNET_STATUS_HANDLE_CREATED:
{
INTERNET_ASYNC_RESULT * pRes = (INTERNET_ASYNC_RESULT * )lpvStatusInformation;
pSession -> hConnect = (HINTERNET)pRes -> dwResult;
TraceLog( L " Connect handle created \r\n " );
SetEvent( pSession -> hConnect );
break ;
}
// 句柄被关闭
case INTERNET_STATUS_HANDLE_CLOSING:
SetEvent( pSession -> hEvent[ 1 ] );
break ;
// 一个请求完成,比如一次句柄创建的请求,或者一次读数据的请求
case INTERNET_STATUS_REQUEST_COMPLETE:
if (ERROR_SUCCESS == ((LPINTERNET_ASYNC_RESULT)
(lpvStatusInformation)) -> dwError)
{
// 设置句柄被创建事件或者读数据成功完成事件
SetEvent( pSession -> hEvent[ 0 ] );
}
else
{
// 如果发生错误,则设置子线程退出事件 这里也是一个陷阱,经常会忽视处理这个错误,
SetEvent( pSession -> hEvent[ 2 ] );
}
break ;
case INTERNET_STATUS_CONNECTION_CLOSED:
SetEvent( pSession -> hEvent[ 2 ] );
break ;
}
};
CHttpSession::CHttpSession( CRequestBase & aRequest )
:m_pRequestBody(NULL),m_pHost(NULL), m_pRequestUrl( NULL ),m_pRecvBuf(NULL),m_pRecvHead(NULL)
,m_dwRecvBodySize( 0 ), m_dwMaxBuf( 0 ) ,m_dwStartPos( 0 ),m_dwRequestBodyLen( 0 ), m_hWnd( 0 ),m_RequestID(EM_Req_Start)
,m_dwThreadID( 0 ),m_hThread( 0 )
{
m_vtRequestHead.clear();
for ( int i = 0 ; i < 3 ; ++ i)
{
hEvent[i] = CreateEvent(NULL,TRUE,FALSE,NULL);
}
NetMsgHead * pHead = aRequest.GetRequestHead();
if ( ! SetRequestHead(pHead) )
return ;
const char * pHost = pHead -> GetHost();
SetServer( pHost );
int port = pHead -> GetPort();
SetPort( port );
const char * pRequestURL = aRequest.GetUrl();
m_pRequestUrl = SetRequestUrl( pRequestURL );
m_RequestID = aRequest.GetRequestID();
bool bPost = aRequest.GetIsPostMsg();
if ( bPost )
{
const char * pData = (( CPostRsqBase * ) & aRequest) -> GetRequestBody();
SetRequestData( pData );
}
else
{
SetRequestData( NULL );
}
}
CHttpSession:: ~ CHttpSession()
{
FREEARRAYIF( m_pRequestBody );
FREEARRAYIF( m_pHost );
FREEARRAYIF( m_pRequestUrl );
FREEARRAYIF( m_pRecvBuf );
FREEARRAYIF( m_pRecvHead );
if (hConnect)
{
InternetCloseHandle(hConnect);
hConnect = NULL;
}
if (hInstance)
{
// 卸载回调
InternetSetStatusCallback(hInstance,NULL);
InternetCloseHandle(hInstance);
hInstance = NULL;
}
if (hRequest)
{
InternetCloseHandle(hRequest);
hRequest = NULL;
}
for ( int i = 0 ; i < 3 ; i ++ )
{
if ( hEvent[i] )
{
CloseHandle(hEvent[i]);
hEvent[i] = NULL;
}
}
}
// void CHttpSession::Reset()
// {
// FREEARRAYIF( m_pRequestBody );
// FREEARRAYIF( m_pHost );
// FREEARRAYIF( m_pRequestUrl );
// FREEARRAYIF( m_pRecvBuf );
// FREEARRAYIF( m_pRecvHead );
//
// m_dwRecvBodySize = 0;
// m_dwMaxBuf = 0;
// m_dwStartPos = 0;
// m_dwRequestBodyLen = 0;
// m_RequestID = EM_Req_Start;
// m_pPort = 0;
//
// if(hConnect)
// {
// InternetCloseHandle(hConnect);
// hConnect = NULL;
// }
//
// if(hInstance)
// {
// // 卸载回调
// InternetSetStatusCallback(hInstance,NULL);
// InternetCloseHandle(hInstance);
// hInstance=NULL;
// }
//
// if(hRequest)
// {
// InternetCloseHandle(hRequest);
// hRequest = NULL;
// }
//
// for ( int i = 0 ; i < 3; i++ )
// {
// if ( hEvent[i] )
// {
// CloseHandle(hEvent[i]);
// hEvent[i] = NULL;
// }
// }
//
// // if(hRequestCompleteEvent)
// // {
// // CloseHandle(hRequestCompleteEvent);
// // hRequestCompleteEvent = NULL;
// // }
// //
// // if(hConnectedEvent)
// // {
// // CloseHandle(hConnectedEvent);
// // hConnectedEvent = NULL;
// // }
// //
// // if(hRequestOpenedEvent)
// // {
// // CloseHandle(hRequestOpenedEvent);
// // hRequestOpenedEvent = NULL;
// // }
//
// for ( unsigned int i = 0 ; i < m_vtRequestHead.size(); i++ )
// {
// char* pItem = m_vtRequestHead[i];
// FREEARRAYIF( pItem );
// }
// m_vtRequestHead.clear();
// }
//
void CHttpSession::SetHWnd( HWND aWnd )
{
m_hWnd = aWnd;
g_hWnd = aWnd;
}
bool CHttpSession::SetHeadValue( const char * aKey, const char * aValue )
{
if ( ! aKey )
return false ;
char * buf = new char [ 256 ];
memset( buf, 0 , 256 );
sprintf( buf, " %s: %s\r\n " , aKey, aValue );
m_vtRequestHead.push_back( buf );
return true ;
}
bool CHttpSession::SetRequestData( const char * aData )
{
if ( ! aData )
return false ;
m_pRequestBody = new char [strlen( aData ) + 1 ];
memset( m_pRequestBody, 0 , strlen( aData ) + 1 );
memcpy( m_pRequestBody, aData, strlen( aData ) );
m_dwRequestBodyLen = strlen( aData );
return true ;
}
bool CHttpSession::SetServer( const char * aServer )
{
if ( ! aServer )
return false ;
m_pHost = new char [strlen( aServer ) + 1 ];
memset( m_pHost, 0 , strlen( aServer ) + 1 );
memcpy( m_pHost, aServer, strlen( aServer ) );
return true ;
}
char * CHttpSession::SetRequestUrl( const char * aUrl )
{
if ( ! aUrl )
return false ;
const char * pUrl = aUrl;
// 检查是否存在http: //
const char * pUrlHead = " http:// " ;
char * pTemp = strstr( pUrl, pUrlHead );
char * pResult = NULL;
// 在开始处
if ( pTemp )
{
if ( pTemp == pUrl )
{
pTemp += strlen( pUrlHead );
// 查找第一个 "/",去掉域名
pTemp = strstr( pTemp, " / " );
if ( ! pTemp )
{
return NULL;
}
pResult = new char [ strlen( pTemp ) + 1 ] ;
memset( pResult, 0 , strlen( pTemp ) + 1 );
memcpy( pResult, pTemp, strlen( pTemp ) );
return pResult;
}
}
else
{
// 没有找到
pResult = new char [ strlen( pUrl ) + 1 ] ;
memset( pResult, 0 , strlen( pUrl ) + 1 );
memcpy( pResult, pUrl, strlen( pUrl ) );
return pResult;
}
return pResult;
}
bool CHttpSession::SetPort( int aPort )
{
if ( aPort < 0 )
{
return false ;
}
m_pPort = aPort;
return true ;
}
bool CHttpSession::SetRequestHead( NetMsgHead * pHead )
{
if ( ! pHead )
return false ;
const char * pszBuf = pHead -> GetAcceptEncoding();
SetHeadValue( T_ACCEPT_ENCODING, pszBuf );
pszBuf = pHead -> GetClientAgent();
SetHeadValue( T_CLIENTAGENT, pszBuf );
pszBuf = pHead -> GetCallingLineID();
SetHeadValue( T_CALLINGLINEID, pszBuf );
pszBuf = pHead -> GetApiVersion();
SetHeadValue( T_APIVERSION, pszBuf );
pszBuf = pHead -> GetContentType();
SetHeadValue( T_CONTENTTYPE, pszBuf );
pszBuf = pHead -> GetXClientType();
SetHeadValue( T_CLIENTTYPE, pszBuf );
pszBuf = pHead -> GetUserid();
SetHeadValue( T_USERID, pszBuf );
pszBuf = pHead -> GetCookie();
SetHeadValue( T_COOKIE, pszBuf );
pszBuf = pHead -> GetAction();
SetHeadValue( T_ACTION, pszBuf );
return true ;
}
BOOL CHttpSession::RetrievingHeaders( HINTERNET hHttp )
{
// LPVOID lpOutBuffer=NULL;
DWORD dwSize = 0 ;
retry:
// This call will fail on the first pass, because no buffer is allocated.
if ( ! HttpQueryInfoA(
hHttp,
HTTP_QUERY_RAW_HEADERS_CRLF,
(LPVOID)m_pRecvHead,
& dwSize,
NULL))
{
if (GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND)
{
TraceLog( L " HttpQueryInfo error : ERROR_HTTP_HEADER_NOT_FOUND \r\n " );
// Code to handle the case where the header isn't available.
return TRUE;
}
else
{
// Check for an insufficient buffer.
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
{
TraceLog( L " HttpQueryInfo error : ERROR_HTTP_HEADER_NOT_FOUND \r\n " );
m_pRecvHead = new char [dwSize];
// Retry the call.
goto retry;
}
else
{
TraceLog( L " HttpQueryInfo error : %d \r\n " , GetLastError() );
// Error handling code.
if (m_pRecvHead)
{
delete [] m_pRecvHead;
}
return FALSE;
}
}
}
TraceLog( L " HttpQueryInfo sucess lpOutBuffer = %s\r\n " , m_pRecvHead );
return TRUE;
}
int CHttpSession::GetRetCode()
{
if ( ! m_pRecvHead )
{
return - 1 ;
}
// 寻找第一个空格
char * pRet1 = strstr( m_pRecvHead, " " );
if ( ! pRet1 )
{
return - 1 ;
}
char * pStart = pRet1 + 1 ;
char * pRet2 = strstr( pStart, " " );
if ( ! pRet2 )
{
return - 1 ;
}
int nLen = pRet2 - pStart;
char * pRetCode = new char [nLen + 1 ];
memset( pRetCode, 0 , nLen + 1 );
memcpy( pRetCode, pStart, nLen );
int nRet = atoi( pRetCode );
FREEARRAYIF( pRetCode );
return nRet;
}
char * CHttpSession::GetRetHeadValue( const char * aKey )
{
if ( ! m_pRecvHead )
{
return NULL;
}
// 寻找key
char * pResult1 = strstr( m_pRecvHead, aKey );
if ( ! pResult1 )
{
return NULL;
}
pResult1 = strstr( pResult1, " : " );
if ( ! pResult1 )
{
return NULL;
}
pResult1 += strlen( " : " );
char * pResult2 = strstr( pResult1, " \r\n " );
int nValueLen = pResult2 - pResult1 ;
char * pRet = new char [nValueLen + 1 ];
memset( pRet, 0 , nValueLen + 1 );
memcpy( pRet, pResult1, nValueLen );
return pRet;
}
const char * CHttpSession::GetRecvHead()
{
return m_pRecvHead;
}