Using WinInet HTTP functions in Full Asynchronous Mode
2012-08-06 14:41
761 查看
Detail
http://www.codeproject.com/Articles/822/Using-WinInet-HTTP-functions-in-Full-AsynchronousAfter the theory, let’s look at some code for some of the points:
1&2: Create the connection using INTERNET_FLAG_ASYNC and setup the callback func:
Collapse | Copy
Code
m_Session = InternetOpen(AGENT_NAME, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC); InternetSetStatusCallback( m_Session, (INTERNET_STATUS_CALLBACK)InternetCallbackFunc );
3&4: Open the connection using InternetOpenUrl and wait for INTERNET_STATUS_REQUEST_COMPLETE
Use the lParamto send a session identifier to your callback. I always use the
thispointer of my class
for it. I assume you know how to handle callbacks.
Collapse | Copy
Code
InternetOpenUrl( m_Session, uurl, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, (LPARAM)this );
The callback will receive a lots of messages then. Here are their orders along with the
dwInternetStatusvalue:
Collapse | Copy
Code
[openUrl] InternetStatus: 60 INTERNET_STATUS_HANDLE_CREATED **At this point you can save the HINTERNET handle using code like this in your callback: INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation; m_hHttpFile = (HINTERNET)(res->dwResult); [openUrl] InternetStatus: 10 [openUrl] InternetStatus: 11 [openUrl] InternetStatus: 20 [openUrl] InternetStatus: 21 [openUrl] InternetStatus: 30 [openUrl] InternetStatus: 31 [openUrl] InternetStatus: 40 [openUrl] InternetStatus: 41 [openUrl] InternetStatus: 100 INTERNET_STATUS_REQUEST_COMPLETE
5: Extract the content-length and set up the INTERNET_BUFFERS structure
Once you have the handle, try to call HttpQueryInfowith
HTTP_QUERY_CONTENT_LENGTHto get the size of
the data to retrieve. This function can fail if the content-length field is not in the HTTP header.
Set up the
INTERNET_BUFFERSstructure.
Collapse | Copy
Code
INTERNET_BUFFERS ib = { sizeof(INTERNET_BUFFERS) }; ib.lpvBuffer = your allocated buffer ib.dwBufferLength = its length
The
dwBufferTotalis provided for your own use and is never modified by WinInet (as
far as I know). I use it to store the total size of the received data.
6&7&8 Read the remaining data in a loop
Use InternetReadFileExwith the
IRF_ASYNCflag to read the remaining data asynchronously. Don’t use
InternetReadFilesince
it is a synchronous function. You must loop on
InternetReadFileExwhile the
ib.dwBufferLengthis not
0. Before each iteration you must adjust the
lpvBufferpointer and reset the
dwBufferLengthmembers of
ib:
add the received length to the pointer and set
dwBufferLengthto your remaining buffer size.
Collapse | Copy
Code
//Start the pump BOOL bOk = InternetReadFileEx( m_hHttpFile, &ib, IRF_ASYNC, (LPARAM)this ); if(!bOk && GetLastError()==ERROR_IO_PENDING) wait... //Pump while( bOk && ib.dwBufferLength!=0 ) { (adjust ib values) bOk = InternetReadFileEx( m_hHttpFile, &ib, IRF_ASYNC, (LPARAM)this ); if(!bOk && GetLastError()==ERROR_IO_PENDING) wait... }
Your callback should receive these notifications (maybe more than once):
Collapse | Copy
Code
[connect] InternetStatus: 40 (receiving response) [connect] InternetStatus: 41 (response received) [connect] InternetStatus: 50 [connect] InternetStatus: 51 and maybe [connect] InternetStatus: 100 INTERNET_STATUS_REQUEST_COMPLETE
The last is received only if
GetLastError()returned
ERROR_IO_PENDING. If you stored the total data size
(in bytes) in the
dwBufferTotalmember, use it to set the final “0” in your string buffer (if it’s a string).
Collapse | Copy
Code
buf[ib.dwBufferTotal] = 0;
9 Close the connection handle
Collapse | Copy
Code
InternetCloseHandle( m_httpFile );
The callback will receive this notification when the handle is closed:
Collapse | Copy
Code
[connect] InternetStatus: 70 INTERNET_STATUS_HANDLE_CLOSING
In most error cases, the connection is closed unexpectedly. If it happens you’ll receive a 70 followed by a 100 (
INTERNET_STATUS_REQUEST_COMPLETE). This can happen anywhere during
the process.
10 Before closing the m_Session handle
You must deregister the callback:Collapse | Copy
Code
InternetSetStatusCallback( m_Session, NULL );
This should help those who tried to go through asynchronous mode in WinInet! Sorry, there are no attached files but you should be able to use the functions
and create nice classes now. If you liked this article please add an entry inmy guestbook and buy me a license of my shareware.
相关文章推荐
- 【转】Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- Using WinInet functions to download a file asynchronously in Delphi
- Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- Asynchronous HTTP Requests in Android Using Volley
- mysql5.7建表时报错clause is not in GROUP BY..this is incompatible with sql_mode=only_full_group_by
- findByEntity is ambiguous in Mapped Statements collection (try using the full name including the nam
- Functions with Variable Argumet lists in C using va_list
- How to use SSH Via HTTP Proxy using Corkscrew in Ubuntu
- Force stop and then start a full crawl on all content sources in a SharePoint 2010 farm using PowerShell(转)
- Be carefull when using string operating function declarated in "string.h"
- Enter Query Mode Search Tricks Using Enter_Query Built-in in Oracle Forms
- Fw:Managing View State in ASP.NET 4 Using the New ViewStateMode Property
- Disabling Shortcut Keys in Full Screen mode
- Upload Large Files in ASP.NET Using HttpModule
- Asynchronous Programming in C# 5.0 using async and await