windows mobile下的wininet的使用

  同步的就不说了,网上和MSDN上有代码。

     对于异步的处理,贴上源代码。参考MSDN上面的代码和网上一些前辈的代码。

     加上了我自己的一些理解和注释,方便后来学习者学习或直接使用。

 

HttpSession.h

 

1 #pragma once
2
3 #include <vector>
4 #include <WinInet.h>
5
6  #define MAXBUFFERSIZE 65535
7
8  #define T_ACCEPT_ENCODING "Accept-Encoding"
9  #define T_CLIENTAGENT "Client-Agent"
10 #define T_CALLINGLINEID "x-up-calling-line-id"
11 #define T_APIVERSION "APIVersion"
12 #define T_USERID "user-id"
13 #define T_ACTION "nAction"
14 #define T_COOKIE "Cookie"
15 #define T_CONTENTTYPE "Content-Type"
16 #define T_CLIENTTYPE "X-ClientType"
17 #define T_CONTENTLEN "Content-Length"
18 #define T_HOST "Host"
19
20 #ifndef FREEIF
21 #define FREEIF(p) {if (p) {delete (p); (p) = NULL;}}
22 #endif
23
24 #ifndef FREEARRAYIF
25 #define FREEARRAYIF(p) {if (p) { delete[] p; (p) = NULL; }}
26 #endif
27
28 void AsyncInternetCallback2(HINTERNET hInternet,
29 DWORD dwContext,
30 DWORD dwInternetStatus,
31 LPVOID lpStatusInfo,
32 DWORD dwStatusInfoLen);
33
34 class CHttpSession
35 {
36 public:
37 CHttpSession();
38 ~CHttpSession();
39
40 public:
41 //添加请求头字符串
42 bool SetHeadValue( const char* aKey, const char* aValue );
43
44 bool SetServer( const char* aServer );
45
46 //URL不包含服务器IP和端口号
47 bool SetRequestUrl( const char* aUrl );
48
49 bool SetPort( int aPort );
50
51 //设置请求数据,仅用于POST请求,GET请求无需使用
52 bool SetRequestData( const char* aData );
53
54 inline const char* GetRecvHead();
55
56 //获取返回的数据体
57 inline const char* GetRecvieData( );
58
59 //获取返回数据的长度
60 inline DWORD GetReceivedDataLen();
61
62 //获取返回码
63 DWORD GetRetCode();
64
65 //获取返回数据头中的字段的值
66 const char* GetRetHeadValue( char* aKey );
67
68 //调用doRequest之前,需要将所有数据都准备好
69 bool DoRequest();
70
71 protected:
72 BOOL RetrievingHeaders(HINTERNET hHttp);
73
74 protected:
75 std::vector<char*> m_vtRequestHead; //请求消息头的字符串
76 char* m_pRequestBody; //请求的消息体
77 DWORD m_dwRequestBodyLen; //请求消息体的长度
78
79 char* m_pHost; //服务器地址
80 int m_pPort; //端口
81 char* m_pRequestUrl; //请求URL地址
82
83 char* m_pRecvHead; //接收到的数据头
84 char* m_pRecvBuf; //接收的缓存
85 DWORD m_dwRecvBodySize; //收到数据的总大小
86 DWORD m_dwMaxBuf; //接收数据缓存的总容器大小
87 DWORD m_dwStartPos; //当前缓存的偏移,已存放在缓存中的数据长度
88 };
89

 

HttpSession.cpp:

 

 

#include "stdafx.h"
#include "HttpSession.h"
#include "Util.h"
#include <wininet.h>
#pragma comment(lib, "Wininet.lib")

HINTERNET hInstance;
HINTERNET hConnect;
HINTERNET hRequest;

HANDLE hConnectedEvent;
HANDLE hRequestOpenedEvent;
HANDLE hRequestCompleteEvent;

BOOL bAllDone ;

extern const char * lpszServer;
extern const char * lpszUrl;

#define CONNECTION_CONTEXT 1
#define REQUEST_CONTEXT    2

#define MAX_BODY_SIZE      10*1024

CHttpSession::CHttpSession()
: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)
{
	hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	hRequestOpenedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}

CHttpSession::~CHttpSession()
{
	FREEARRAYIF( m_pRequestBody );
	FREEARRAYIF( m_pHost );
	FREEARRAYIF( m_pRequestUrl );
	FREEARRAYIF( m_pRecvBuf );
	FREEARRAYIF( m_pRecvHead );
}

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 ) );

	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;
}

bool CHttpSession::SetRequestUrl( const char* aUrl )
{
	if( !aUrl )
		return false;

	m_pRequestUrl = new char[strlen( aUrl ) + 1 ] ;
	memset( m_pRequestUrl, 0, strlen( aUrl ) + 1 );
	memcpy( m_pRequestUrl, aUrl, strlen( aUrl ) );

	return true;

}

bool CHttpSession::SetPort( int aPort )
{
	if ( aPort < 0 )
	{
		return false;
	}
	m_pPort = aPort;
	return true;
}

bool CHttpSession::DoRequest()
{
	//异步
	hInstance = InternetOpenA( "TYYD_Mobile_6_0_240_320_E806_C_GG_1_0_0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC); // ASYNC Flag

	if( !hInstance ) //有些手机用上面的参数访问不了Internet
		hInstance=InternetOpenA("TYYD_Mobile_6_0_240_320_E806_C_GG_1_0_0",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,INTERNET_FLAG_ASYNC);
	if ( !hInstance )
	{
		TraceLog( L"InternetOpen failed, error : %d \r\n",GetLastError() );
		return false;
	}
	TraceLog( L"InternetOpen suceess :%d \r\n",GetLastError() );

	// Setup callback function
	if (InternetSetStatusCallbackA(hInstance,(INTERNET_STATUS_CALLBACK)&AsyncInternetCallback2) == 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
	hConnect = InternetConnectA(hInstance,m_pHost, m_pPort,NULL,NULL,INTERNET_SERVICE_HTTP,0,1); // Connection handle's Context

	if (hConnect == NULL)
	{
		TraceLog( L"hConnect == NULL, errno = %d \r\n ",GetLastError() );

		if (GetLastError() != ERROR_IO_PENDING)
		{
			TraceLog( L"InternetConnect failed, error %d  ",GetLastError() );

			return false; 
		}
	}
	// Wait until we get the connection handle
	WaitForSingleObject(hConnectedEvent, INFINITE);
	TraceLog( L"Ready To openRequest \r\n");

	char* pVerb = !m_pRequestBody ? "GET" : " POST" ;

	const char * lpszUrl = "/portalapi/imagedownload?key=1000002845492.jpg&type=content";

	// Open the request
	hRequest = HttpOpenRequestA(hConnect, 
		pVerb, 
		m_pRequestUrl,
		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,
		2);  // Request handle's context 

	if (hRequest == NULL)
	{
		if (GetLastError() != ERROR_IO_PENDING)
		{
			TraceLog( L"HttpOpenRequest failed, error = %d \r\n", GetLastError() );
			return false;
		}
	}

	// Wait until we get the request handle
	WaitForSingleObject(hRequestOpenedEvent, INFINITE);

	TraceLog( L"HttpOpenRequest Sucess\r\n" );

	//Add Request HeadInfo
	for( int i = 0 ; i < m_vtRequestHead.size(); i++ )
	{
		char* pItem = m_vtRequestHead[i];
		HttpAddRequestHeadersA(hRequest, pItem, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE );
	}

	int nRequestBody = !m_pRequestBody ? 0 : strlen( m_pRequestBody );

	// Sends the specified request to the HTTP server.
	if (!HttpSendRequestA(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
		m_pRequestBody,    // Pointer to a buffer containing any optional data to be sent immediately after the request headers.
		m_dwRequestBodyLen ))                // 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(hRequestCompleteEvent, INFINITE);

	TraceLog( L"------------------- Read the response -------------------\r\n" );
	
	//获取响应数据包头
	RetrievingHeaders( hRequest );

	DWORD dwLen = 0;

	InternetQueryDataAvailable(hRequest,&dwLen,0,0);

	char* lpReadBuff = new char[MAX_BODY_SIZE];	
	do
	{
		memset(lpReadBuff, 0, MAX_BODY_SIZE);
		INTERNET_BUFFERSA InetBuff;
		FillMemory(&InetBuff, sizeof(InetBuff), 0);
		InetBuff.dwStructSize = sizeof(InetBuff);
		InetBuff.lpvBuffer = (LPVOID)lpReadBuff;
		InetBuff.dwBufferLength = MAX_BODY_SIZE - 1;

		TraceLog( L"Calling InternetReadFileExA \r\n" );

		if ( !InternetReadFileExA(hRequest,&InetBuff,IRF_ASYNC, 2) )
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{
				TraceLog( L"Waiting for InternetReadFileEx to complete \r\n" );
				WaitForSingleObject(hRequestCompleteEvent, INFINITE);
			}
			else
			{
				TraceLog( L"InternetReadFileEx failed, error :%d \r\n", GetLastError() );
				return false;
			}
		}
		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);
		}
		else
		{
			m_dwRecvBodySize += InetBuff.dwBufferLength;

			if ( !m_pRecvBuf )
			{
				m_pRecvBuf = new char[MAX_BODY_SIZE];
				memset( m_pRecvBuf, 0, MAX_BODY_SIZE );
				m_dwMaxBuf = MAX_BODY_SIZE;
			}

			//剩余空间不足,重新分配空间
			if ( m_dwMaxBuf - m_dwStartPos < InetBuff.dwBufferLength + 1)
			{
				TraceLog( L" Memspace is not enough!" );
				char* pTempBuf = m_pRecvBuf;
				m_pRecvBuf = new char[m_dwMaxBuf + MAX_BODY_SIZE];
				memset( m_pRecvBuf, 0, m_dwMaxBuf + MAX_BODY_SIZE);
				m_dwMaxBuf = m_dwMaxBuf + MAX_BODY_SIZE;
				memcpy( m_pRecvBuf, pTempBuf, m_dwStartPos);
				delete[] pTempBuf;
				pTempBuf = NULL;
			}

			TraceLog( L" Memspace is enough!" );
			memcpy( m_pRecvBuf + m_dwStartPos, lpReadBuff, InetBuff.dwBufferLength );
			TraceLog( L"InternetReadFileEx startPos = %d, curRecvLen = %d, totalSize = %d! \r\n", m_dwStartPos, InetBuff.dwBufferLength , m_dwRecvBodySize);
			m_dwStartPos += InetBuff.dwBufferLength;
		}

	} while (bAllDone == FALSE);

	FREEARRAYIF( lpReadBuff );
	return true;
}

BOOL CHttpSession::RetrievingHeaders(HINTERNET hHttp)
{
	//LPVOID lpOutBuffer=NULL;
	DWORD dwSize = 0;
	FREEARRAYIF( m_pRecvHead );

retry:

	// This call will fail on the first pass, because no buffer is allocated.
	if(!HttpQueryInfo(
		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;
}

DWORD CHttpSession::GetRecvieData()
{
	return m_pRecvBuf;
}

const char* CHttpSession::GetRecvHead()
{
	return m_pRecvHead;
}

DWORD CHttpSession::GetReceivedDataLen()
{
	return m_dwRequestBodyLen;
}

void AsyncInternetCallback2(HINTERNET hInternet,
										  DWORD dwContext,
										  DWORD dwInternetStatus,
										  LPVOID lpStatusInfo,
										  DWORD dwStatusInfoLen)
{
	TraceLog( L"dwContext = %d, dwInternetStatus = %d \r\n", dwContext, dwInternetStatus );

	switch(dwContext)
	{
	case 1: // Connection handle
		if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
		{
			INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
			hConnect = (HINTERNET)pRes->dwResult;
			TraceLog( L"Connect handle created \r\n");
			SetEvent(hConnectedEvent);
		}
		break;
	case 2: // Request handle
		switch(dwInternetStatus)
		{
		case INTERNET_STATUS_HANDLE_CREATED:
			{
				INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
				hRequest = (HINTERNET)pRes->dwResult;

				TraceLog( L"Request handle created \r\n");

				SetEvent(hRequestOpenedEvent);
			}
			break;
		case INTERNET_STATUS_REQUEST_SENT:
			{
				DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
				TraceLog( L"Bytes Sent:%d \r\n", lpBytesSent );
			}
			break;
		case INTERNET_STATUS_REQUEST_COMPLETE:
			{
				INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
				TraceLog( L"Function call finished, dwResult: %d, dwError:  \r\n", pAsyncRes->dwResult, pAsyncRes->dwError);

				SetEvent(hRequestCompleteEvent);
			}
			break;
		case INTERNET_STATUS_RECEIVING_RESPONSE:
			TraceLog( L"Receiving Response \r\n" );
			break;
		case INTERNET_STATUS_RESPONSE_RECEIVED:
			{
				DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;
				if (*dwBytesReceived == 0)
					bAllDone = TRUE;
				TraceLog( L"Receiving %d \r\n", dwBytesReceived);
			}
		}

		break;
	default:break;
	}
}

测试环境:vs2008 + windows mobile 2003
测试代码:
	CHttpSession* pSession = new CHttpSession();

	pSession->SetServer( lpszServer );
	pSession->SetPort( 8080 );
	pSession->SetRequestUrl( lpszUrl );
	pSession->SetRequestData( NULL );

	pSession->SetHeadValue( T_ACCEPT_ENCODING, "gzip" );
	pSession->SetHeadValue( T_CLIENTAGENT, "TYYD_Mobile_6_0_240_320_E806_C_GG_1_0_0" );
	pSession->SetHeadValue( T_CALLINGLINEID, "18912345677" );
	pSession->SetHeadValue( T_APIVERSION, "1.0.0" );
	pSession->SetHeadValue( T_CONTENTTYPE, "application/xml" );
	pSession->SetHeadValue( T_CLIENTTYPE, "1");
	pSession->SetHeadValue( T_USERID, "" );
	pSession->SetHeadValue( T_COOKIE, "" );
	pSession->SetHeadValue( T_ACTION, "" );	

	pSession->DoRequest();
posted @ 2010-12-20 18:14  狼哥2  阅读(372)  评论(0编辑  收藏  举报