HTTP Client Using WININET Asynchronously

.
async wininet


Introduction

WININET is a set of easy to use APIs that enable you to interact with the FTP and HTTP protocols without having to worry about protocol specifications or even Winsock calls. Other WININET benefits include:

  • Built in caching support
  • Supports proxy servers
  • Supports IPv6

Using The Code

Attached with this post is a wrapper class around the WININET API demonstrating how to use it asynchronously, this is how to use the class:

#include "wininet.h"

....

	CWininet myWininet;
	if (myWininet.Connect("http://veridium.net"), 80, _T("AsyncWininet"), 20000)  //timeout
	{
		if (myWininet.SendRequest("/", _T(""), 20000)) //timeout
		//index page, no referer
		{
			char szBuff[1024];

			while ((nLen = myWininet.Read((PBYTE)szBuff, 1024, 20000)) > 0)
			{
				szBuff[nLen] = 0;
				.....
			}
		}
	}


How Does It Work

First we call InternetOpen using INTERNET_FLAG_ASYNC:
	if (!(m_hInstance = InternetOpen(lpszAgent, 
					INTERNET_OPEN_TYPE_PRECONFIG,
					NULL,
					NULL,
					INTERNET_FLAG_ASYNC)))
	{
               return FALSE;
	}


Then we set a callback function that would be called by the system when an asynchronous operation complets:

	if (InternetSetStatusCallback(m_hInstance,
				(INTERNET_STATUS_CALLBACK)&Callback)
				== INTERNET_INVALID_STATUS_CALLBACK)
	{
		return FALSE;
	}



Now in subsequent API calls we pass a predefined flag so that we recognize this operation and this object from inside the callback function:

	m_context.dwContext	= CONTEXT_CONNECT;
	m_context.pObj		= this;

	m_hConnect = InternetConnect(m_hInstance, 
					lpszAddr,
					uPort,
					NULL,
					NULL,
					INTERNET_SERVICE_HTTP,
					INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE,
					(DWORD)&m_context);


And inside the callback we signal an event for each completed operation to notifiy the waiting thread:
	switch(pContext->dwContext)
	{
	case CONTEXT_CONNECT:
		if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
		{
			INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
			pContext->pObj->m_hConnect = (HINTERNET)pRes->dwResult;
			SetEvent(pContext->pObj->m_hConnectedEvent);
		}
		break;
	......

	}


History

20 MAR 11: first release.

.
.

3 Comments


  1. Bruno
    Mar 21, 2011

    Thank you !
    Looks like we still have REAL developers with native skills !


  2. Johnathon
    Jun 29, 2011

    You need to also call InternetSetStatusCallback(HINSTANCE ,NULL) on the hinstance you origionally called it on before you call InternetCloseHandle() otherwise you will have a resource leak


  3. Johnathon
    Jun 29, 2011

    HINTERNET , excuse me