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