HTTP请求网页(包括HTTPS)

借鉴了网上的,忘记是在哪里看到的了。 增加了对HTTPS的支持。用到了MFC的CString,可以自行修改无需MFC。直接贴代码:

 

WebClient.h:

#pragma once

#include <Windows.h>

#include <winhttp.h>

#pragma comment(lib, "Winhttp.lib")

#include <vector>



#ifdef _DLL

#ifndef _AFXDLL

#error 需要MFC支持!

#endif

#endif



#ifndef _UNICODE

#error 只能用于UNICODE项目中!

#endif



//小型动态缓冲区

//仅支持基本数据类型

template<typename T>

class DynamicBuffer

{

	enum {

		DEFAULT_SIZE = 32000,	//默认初始大小

		GROW_SIEZ = 32000,		//每次增长大小

	};

private:

	T *m_pData;

	size_t m_nData;

	size_t m_nBuffer;

public:

	explicit DynamicBuffer(const T *pData = NULL, size_t nData = 0);

	//允许用右值构造

	DynamicBuffer(const DynamicBuffer &&RValue);

	//允许用右值赋值

	DynamicBuffer& operator = (const DynamicBuffer &&RValue);

	~DynamicBuffer();

	//追加数据

	void Append(const T *pData, size_t nData);

	//清空所有数据,恢复默认构造后的状态

	void Clear();

	//释放所有内存,一般在不再使用时才调用

	bool Release();

	//获取保存的数据大小

	size_t Size()

	{

		return m_nData;

	}

	const T* Data()

	{

		return m_pData;

	}

	operator const T*()

	{

		return m_pData;

	}

private:

	DynamicBuffer(const DynamicBuffer&);

	DynamicBuffer& operator = (const DynamicBuffer&);

};



class WebClient

{

public:

	enum RetCode {

		SUCCESS = 0,

		INVALID_URL = 1,

		WINHTTP_ERROR = 2,

		INTERNET_ERROR = 3,

		TIMEOUT_ERROR = 4,

		CREATE_FILE_ERROR = 5,

	};

	enum {

		ANSI = 1,

		UTF8 = 2,

	};

private:

	HINTERNET m_hSession;

	CStringW m_strUserAgent;

	int m_CharSet;

public:

	explicit WebClient(LPCWSTR wszUserAgent = L"Mozilla/5.0");

	~WebClient();

	//清理Cookie,重置会话

	void ClearAll();

	//发起GET请求,获取页面HTML

	RetCode Get(LPCWSTR wszUrl, CStringW &strHtml,int iCnt = 0);

	RetCode GetEx(LPCWSTR wszUrl, const CStringW &strHead, CStringW &strHtml,int iCnt = 0);

	RetCode GetEx(LPCWSTR wszUrl, const std::vector<CStringW> &vec_strHead, CStringW &strHtml,int iCnt =0);

	//发起POST请求,获取返回的HTML

	RetCode Post(LPCWSTR wszUrl, const CStringW &strPostData, CStringW &strHtml);

	RetCode PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const CStringW &strHead, CStringW &strHtml);

	RetCode PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const std::vector<CStringW> &vec_strHead, CStringW &strHtml);

	//下载文件

	RetCode DownloadFile(LPCWSTR wszUrl, LPCWSTR wszFilePath);

	//设置超时值

	bool SetTimeouts(DWORD dwConnectTimeout, DWORD dwTransmissionTimeout);

	//设置代理

	bool SetProxy(const CStringW &strProxy);

	//取消代理

	bool RemoveProxy();

	//设置目标网站编码,默认为UTF8

	bool CharSet(int iCharSet);

private:

	enum {

		MAX_URL_LENGTH = 2084,

		TEMP_BUFFER_SIZE = 4096,//4000,

	};

	//分析URL

	bool ParseUrl(LPCWSTR wszUrl, int &iProtocol, WORD &nPort, CStringW &strHostName, CStringW &strUrlPath);

	//编码转换

	CStringW UTF8ToUTF16(LPCSTR szUTF8, int nLen = -1);

	CStringW AnsiToUTF16(LPCSTR szAnsi, int nLen = -1);

	CStringA UTF16ToUTF8(LPCWSTR wszUTF16, int nLen = -1);



private:

	WebClient(const WebClient&);

	WebClient& operator = (const WebClient&);

};

  WebClient.cpp:

#include "stdafx.h"

#include "WebClient.h"



#ifdef _DEBUG

#define new DEBUG_NEW

#endif





//小型动态缓冲区

template<typename T>

DynamicBuffer<T>::DynamicBuffer(const T *pData /*=NULL*/, size_t nData /*=0*/)

{

	ASSERT(!(!pData && nData != 0));

	if (nData > DEFAULT_SIZE)

		m_nBuffer = nData + GROW_SIEZ;

	else

		m_nBuffer = DEFAULT_SIZE;

	m_pData = (T*)malloc(m_nBuffer * sizeof(T));

	memset(m_pData, 0, m_nBuffer * sizeof(T));

	if (pData)

		memcpy_s(m_pData, m_nBuffer * sizeof(T), pData, nData * sizeof(T));

	m_nData = nData;

}



//允许用右值构造

template<typename T>

DynamicBuffer<T>::DynamicBuffer(const DynamicBuffer &&RValue)

{

	m_pData = RValue.m_pData;

	m_nData = RValue.m_nData;

	m_nBuffer = RValue.m_nBuffer;

}



//允许用右值赋值

template<typename T>

DynamicBuffer<T>& DynamicBuffer<T>::operator = (const DynamicBuffer &&RValue)

{

	if (m_pData)

		free(m_pData);

	m_pData = RValue.m_pData;

	m_nData = RValue.m_nData;

	m_nBuffer = RValue.m_nBuffer;

	return *this;

}



template<typename T>

DynamicBuffer<T>::~DynamicBuffer()

{

	Release();

}



//追加数据

template<typename T>

void DynamicBuffer<T>::Append(const T *pData, size_t nData)

{

	ASSERT(!(pData == NULL && nData != 0));

	if (nData > m_nBuffer - m_nData)

	{

		//需要重新分配内存

		size_t nNewBuffer = 0;

		if (nData > GROW_SIEZ)

			nNewBuffer = m_nData + nData + GROW_SIEZ;

		else

			nNewBuffer = m_nBuffer + GROW_SIEZ;

		m_pData = (T*)realloc(m_pData, nNewBuffer * sizeof(T));

		memset(m_pData + m_nBuffer, 0, (nNewBuffer - m_nBuffer) * sizeof(T));

		m_nBuffer = nNewBuffer;

	}

	memcpy_s(m_pData + m_nData, (m_nBuffer - m_nData) * sizeof(T), pData, nData * sizeof(T));

	m_nData += nData;

}



//释放所有内存,一般在不再使用时才调用

template<typename T>

bool DynamicBuffer<T>::Release()

{

	if (m_pData)

	{

		free(m_pData);

		m_pData = NULL;

		m_nData = 0;

		m_nBuffer = 0;

		return true;

	}

	else

		return false;

}



//清空所有数据,恢复默认构造后的状态

template<typename T>

void DynamicBuffer<T>::Clear()

{

	if (m_pData && m_nBuffer == DEFAULT_SIZE)

	{

		//已经是默认构造后的大小,清空下数据即可

		memset(m_pData, 0, m_nBuffer);

		m_nData = 0;

		return;

	}

	if (m_pData)

		free(m_pData);

	m_pData = (T*)malloc(DEFAULT_SIZE * sizeof(T));

	memset(m_pData, 0, DEFAULT_SIZE * sizeof(T));

	m_nBuffer = DEFAULT_SIZE;

	m_nData = 0;

}







WebClient::WebClient(LPCWSTR wszUserAgent /*= L"Mozilla/5.0"*/)

{

	ASSERT(wszUserAgent != NULL);

	m_CharSet = UTF8;

	m_strUserAgent = wszUserAgent;

	m_hSession = WinHttpOpen(m_strUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY,

		WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, NULL);

	//自动跟踪所有重定向

	DWORD dwOption = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;

	BOOL bSuccessSet = WinHttpSetOption(m_hSession, WINHTTP_OPTION_REDIRECT_POLICY, &dwOption, sizeof(DWORD));



	ASSERT(m_hSession != NULL && bSuccessSet);

}



WebClient::~WebClient()

{

	if (m_hSession)

		WinHttpCloseHandle(m_hSession);

}



//清理Cookie,重置会话

void WebClient::ClearAll()

{

	if (m_hSession)

		WinHttpCloseHandle(m_hSession);

	m_hSession = WinHttpOpen(m_strUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY,

		WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, NULL);

	//自动跟踪所有重定向

	DWORD dwOption = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;

	BOOL bSuccessSet = WinHttpSetOption(m_hSession, WINHTTP_OPTION_REDIRECT_POLICY, &dwOption, sizeof(DWORD));



	ASSERT(m_hSession != NULL && bSuccessSet);

}





//发起GET请求,获取页面HTML

WebClient::RetCode WebClient::Get(LPCWSTR wszUrl, CStringW &strHtml,int iCnt)

{

	return GetEx(wszUrl, L"", strHtml,iCnt);

}



WebClient::RetCode WebClient::GetEx(LPCWSTR wszUrl, const CStringW &strHead, CStringW &strHtml,int iCnt)

{

	std::vector<CStringW> vec_strHead;

	if (!strHead.IsEmpty())

		vec_strHead.push_back(strHead);

	return GetEx(wszUrl, vec_strHead, strHtml,iCnt);

}



WebClient::RetCode WebClient::GetEx(LPCWSTR wszUrl, const std::vector<CStringW> &vec_strHead, CStringW &strHtml,int iCnt)

{

	ASSERT(wszUrl != NULL);

	//解析URL

	int iProtocal;

	WORD nPort;

	CStringW strHostName, strUrlPath;

	if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath))

		return INVALID_URL;



	HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL);

	if (!hConnect)

		return WINHTTP_ERROR;

	//不接受缓存

	DWORD dwFlags = WINHTTP_FLAG_REFRESH;

	if (iProtocal == INTERNET_SCHEME_HTTPS)

	{

		dwFlags |= WINHTTP_FLAG_SECURE;

	}

	HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", strUrlPath, NULL,

		WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);

	if (!hRequest)

	{

		WinHttpCloseHandle(hConnect);

		return WINHTTP_ERROR;

	}

	//////////////////////////////////////////////////////////////////////////

	//添加请求头 FOR HTTPS

	DWORD dwBuffLen = sizeof(dwFlags);           

	WinHttpQueryOption (hRequest, WINHTTP_OPTION_SECURITY_FLAGS,

		(LPVOID)&dwFlags, &dwBuffLen);

	dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;

	dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;

	dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;

	//    dwFlags |= SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;



	WinHttpSetOption (hRequest, WINHTTP_OPTION_SECURITY_FLAGS,

		&dwFlags, sizeof (dwFlags) );

	////////////////////end//////////////////////////////////////////////////

	for (size_t i=0; i<vec_strHead.size(); i++)

	{

		if (!vec_strHead[i].IsEmpty())

		{

			WinHttpAddRequestHeaders(hRequest, vec_strHead[i],

				-1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE);

		}

	}

	//////////////////////////////////////////////////////////////////////////

	//发送请求

	if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, 

		WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//接收内容

	if (!WinHttpReceiveResponse(hRequest, NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//读出内容

	DynamicBuffer<char> DyBuffData;

	char *pTempBuffer = new char[TEMP_BUFFER_SIZE];

	DWORD dwRead = 0;

	//写入文件

	FILE *fp;

	char name[64];

	ZeroMemory(name,64);

	//这边我所请求的数据是已知的jpg图片

	sprintf(name,"%d.jpg",iCnt);

	if ((fp = fopen(name, "ab+")) == NULL)  // 存储图片

		return CREATE_FILE_ERROR;

	do 

	{

		memset(pTempBuffer, 0, TEMP_BUFFER_SIZE);

		if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead))

		{

			DWORD dwErrorCode = GetLastError();

			RetCode retcode;

			if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

				dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

				retcode = INTERNET_ERROR;

			else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

				retcode = TIMEOUT_ERROR;

			else

				retcode = WINHTTP_ERROR;

			delete [] pTempBuffer;

			WinHttpCloseHandle(hRequest);

			WinHttpCloseHandle(hConnect);

			return retcode;

		}

		dwRead > 0?fwrite(pTempBuffer, dwRead,1 ,fp):NULL;

		DyBuffData.Append(pTempBuffer, dwRead);



	} while (dwRead > 0);



	delete [] pTempBuffer;

	WinHttpCloseHandle(hRequest);

	WinHttpCloseHandle(hConnect);

	//关闭文件

	fclose(fp);

	//进行编码转换

	if (m_CharSet == UTF8)

	{

		strHtml = UTF8ToUTF16(DyBuffData, DyBuffData.Size());

	}

	else

	{

		strHtml = AnsiToUTF16(DyBuffData, DyBuffData.Size());

	}



	return SUCCESS;

}



//下载文件

WebClient::RetCode WebClient::DownloadFile(LPCWSTR wszUrl, LPCWSTR wszFilePath)

{

	ASSERT(wszUrl != NULL && wszFilePath != NULL);

	//解析URL

	int iProtocal;

	WORD nPort;

	CStringW strHostName, strUrlPath;

	if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath))

		return INVALID_URL;



	HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL);

	if (!hConnect)

		return WINHTTP_ERROR;

	//不接受缓存

	DWORD dwFlags = WINHTTP_FLAG_REFRESH;

	if (iProtocal == INTERNET_SCHEME_HTTPS)

		dwFlags |= WINHTTP_FLAG_SECURE;

	HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", strUrlPath, NULL,

		WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);

	if (!hRequest)

	{

		WinHttpCloseHandle(hConnect);

		return WINHTTP_ERROR;

	}

	//发送请求

	if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, 

		WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//接收内容

	if (!WinHttpReceiveResponse(hRequest, NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//读出内容,写入到文件

	CFile File;

	if (!File.Open(wszFilePath, CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite))

	{

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return CREATE_FILE_ERROR;

	}

	char *pTempBuffer = new char[TEMP_BUFFER_SIZE];

	DWORD dwRead = 0;

	do 

	{

		memset(pTempBuffer, 0, TEMP_BUFFER_SIZE);

		if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead))

		{

			DWORD dwErrorCode = GetLastError();

			RetCode retcode;

			if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

				dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

				retcode = INTERNET_ERROR;

			else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

				retcode = TIMEOUT_ERROR;

			else

				retcode = WINHTTP_ERROR;

			delete [] pTempBuffer;

			WinHttpCloseHandle(hRequest);

			WinHttpCloseHandle(hConnect);

			//未下载完,网络异常,删除文件

			File.Close();

			::DeleteFileW(wszFilePath);

			return retcode;

		}

		File.Write(pTempBuffer, dwRead);



	} while (dwRead > 0);



	delete [] pTempBuffer;

	WinHttpCloseHandle(hRequest);

	WinHttpCloseHandle(hConnect);

	File.Close();



	return SUCCESS;

}



//发起POST请求,获取返回的HTML

WebClient::RetCode WebClient::Post(LPCWSTR wszUrl, const CStringW &strPostData, CStringW &strHtml)

{

	return PostEx(wszUrl, strPostData, L"", strHtml);

}



WebClient::RetCode WebClient::PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const CStringW &strHead, CStringW &strHtml)

{

	std::vector<CStringW> vec_strHead;

	if (!strHead.IsEmpty())

		vec_strHead.push_back(strHead);

	return PostEx(wszUrl, strPostData, vec_strHead, strHtml);

}



WebClient::RetCode WebClient::PostEx(LPCWSTR wszUrl, const CStringW &strPostData, const std::vector<CStringW> &vec_strHead, CStringW &strHtml)

{

	ASSERT(wszUrl != NULL);

	//解析URL

	int iProtocal;

	WORD nPort;

	CStringW strHostName, strUrlPath;

	if (!ParseUrl(wszUrl, iProtocal, nPort, strHostName, strUrlPath))

		return INVALID_URL;



	HINTERNET hConnect = WinHttpConnect(m_hSession, strHostName, nPort, NULL);

	if (!hConnect)

		return WINHTTP_ERROR;

	//不接受缓存

	DWORD dwFlags = WINHTTP_FLAG_REFRESH;

	if (iProtocal == INTERNET_SCHEME_HTTPS)

		dwFlags |= WINHTTP_FLAG_SECURE;

	HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", strUrlPath, NULL,

		WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);

	if (!hRequest)

	{

		WinHttpCloseHandle(hConnect);

		return WINHTTP_ERROR;

	}

	//添加POST必备的请求头

	WinHttpAddRequestHeaders(hRequest, L"Content-Type: application/x-www-form-urlencoded",

		-1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE);

	//添加其它请求头

	for (size_t i=0; i<vec_strHead.size(); i++)

	{

		if (!vec_strHead[i].IsEmpty())

		{

			WinHttpAddRequestHeaders(hRequest, vec_strHead[i],

				-1L, WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_REPLACE);

		}

	}

	//转换编码

	CStringA strPostData_utf8 = UTF16ToUTF8(strPostData);

	//发送请求

	if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, 

		(LPSTR)(LPCSTR)strPostData_utf8, strPostData_utf8.GetLength(), strPostData_utf8.GetLength(), NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//接收内容

	if (!WinHttpReceiveResponse(hRequest, NULL))

	{

		DWORD dwErrorCode = GetLastError();

		RetCode retcode;

		if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

			dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

			retcode = INTERNET_ERROR;

		else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

			retcode = TIMEOUT_ERROR;

		else

			retcode = WINHTTP_ERROR;

		WinHttpCloseHandle(hRequest);

		WinHttpCloseHandle(hConnect);

		return retcode;

	}

	//读出内容

	DynamicBuffer<char> DyBuffData;

	char *pTempBuffer = new char[TEMP_BUFFER_SIZE];

	DWORD dwRead = 0;

	do 

	{

		memset(pTempBuffer, 0, TEMP_BUFFER_SIZE);

		if (!WinHttpReadData(hRequest, pTempBuffer, TEMP_BUFFER_SIZE, &dwRead))

		{

			DWORD dwErrorCode = GetLastError();

			RetCode retcode;

			if (dwErrorCode == ERROR_WINHTTP_NAME_NOT_RESOLVED || dwErrorCode == ERROR_WINHTTP_CANNOT_CONNECT ||

				dwErrorCode == ERROR_WINHTTP_INVALID_SERVER_RESPONSE || dwErrorCode == ERROR_WINHTTP_CONNECTION_ERROR)

				retcode = INTERNET_ERROR;

			else if (dwErrorCode == ERROR_WINHTTP_TIMEOUT)

				retcode = TIMEOUT_ERROR;

			else

				retcode = WINHTTP_ERROR;

			delete [] pTempBuffer;

			WinHttpCloseHandle(hRequest);

			WinHttpCloseHandle(hConnect);

			return retcode;

		}

		DyBuffData.Append(pTempBuffer, dwRead);



	} while (dwRead > 0);



	delete [] pTempBuffer;

	WinHttpCloseHandle(hRequest);

	WinHttpCloseHandle(hConnect);



	//进行编码转换

	if (m_CharSet == UTF8)

		strHtml = UTF8ToUTF16(DyBuffData, DyBuffData.Size());

	else

		strHtml = AnsiToUTF16(DyBuffData, DyBuffData.Size());



	return SUCCESS;	

}





//分析URL

bool WebClient::ParseUrl(LPCWSTR wszUrl, int &iProtocol, WORD &nPort, CStringW &strHostName, CStringW &strUrlPath)

{

	ASSERT(wszUrl != NULL);



	WCHAR *wszHostName = new WCHAR[MAX_URL_LENGTH+1];

	WCHAR *wszUrlPath = new WCHAR[MAX_URL_LENGTH+1];

	memset(wszHostName, 0 , MAX_URL_LENGTH+1);

	memset(wszUrlPath, 0, MAX_URL_LENGTH+1);

	URL_COMPONENTS urlComp = {sizeof(URL_COMPONENTS)};

	urlComp.lpszHostName = wszHostName;

	urlComp.dwHostNameLength = MAX_URL_LENGTH;

	urlComp.lpszUrlPath = wszUrlPath;

	urlComp.dwUrlPathLength = MAX_URL_LENGTH;

	

	BOOL bSuccessParse = WinHttpCrackUrl(wszUrl, NULL, NULL, &urlComp);

	if (bSuccessParse)

	{

		iProtocol = urlComp.nScheme;

		nPort = urlComp.nPort;

		strHostName = urlComp.lpszHostName;

		strUrlPath = urlComp.lpszUrlPath;

	}



	delete [] wszHostName;

	delete [] wszUrlPath;

	if (bSuccessParse)

		return true;

	else

		return false;

}



//编码转换

CStringW WebClient::UTF8ToUTF16(LPCSTR szUTF8, int nLen /*= -1*/)

{

	//先获取转换后需要的缓冲区大小

	DWORD nWszLen = MultiByteToWideChar(CP_UTF8, NULL, szUTF8, nLen, NULL, NULL);



	CStringW strUTF16;

	nWszLen = MultiByteToWideChar(CP_UTF8, NULL, szUTF8, nLen, strUTF16.GetBuffer(nWszLen), nWszLen);

	strUTF16.ReleaseBuffer(nWszLen);



	return strUTF16;

}



CStringW WebClient::AnsiToUTF16(LPCSTR szAnsi, int nLen /*= -1*/)

{

	//先获取转换后需要的缓冲区大小

	DWORD nWszLen = MultiByteToWideChar(CP_ACP, NULL, szAnsi, nLen, NULL, NULL);



	CStringW strUTF16;

	nWszLen = MultiByteToWideChar(CP_ACP, NULL, szAnsi, nLen, strUTF16.GetBuffer(nWszLen), nWszLen);

	strUTF16.ReleaseBuffer(nWszLen);



	return strUTF16;

}



CStringA WebClient::UTF16ToUTF8(LPCWSTR wszUTF16, int nLen /*= -1*/)

{

	//先获取转换后需要的缓冲区大小

	DWORD nszLen = WideCharToMultiByte(CP_UTF8, NULL, wszUTF16, nLen, NULL, NULL, NULL, NULL);



	CStringA strUTF8;

	nszLen = WideCharToMultiByte(CP_UTF8, NULL, wszUTF16, nLen, strUTF8.GetBuffer(nszLen), nszLen, NULL, NULL);

	strUTF8.ReleaseBuffer(nszLen);



	return strUTF8;

}



//设置超时值

bool WebClient::SetTimeouts(DWORD dwConnectTimeout, DWORD dwTransmissionTimeout)

{

	if (WinHttpSetTimeouts(m_hSession, 0, dwConnectTimeout, dwTransmissionTimeout, dwTransmissionTimeout))

		return true;

	else

		return false;

}



//设置代理

bool WebClient::SetProxy(const CStringW &strProxy)

{

	WINHTTP_PROXY_INFO ProxyInfo = {WINHTTP_ACCESS_TYPE_NAMED_PROXY,

		(LPWSTR)(LPCWSTR)strProxy, (LPWSTR)(LPCWSTR)strProxy};

	if (WinHttpSetOption(m_hSession, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof(WINHTTP_PROXY_INFO)))

		return true;

	else

		return false;

}



//取消代理

bool WebClient::RemoveProxy()

{

	WINHTTP_PROXY_INFO ProxyInfo = {WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL};

	if (WinHttpSetOption(m_hSession, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof(WINHTTP_PROXY_INFO)))

		return true;

	else

		return false;

}



//设置目标网站编码

bool WebClient::CharSet(int iCharSet)

{

	if (iCharSet != ANSI && iCharSet != UTF8)

		return false;

	m_CharSet = iCharSet;

	return true;

}

  调用:

 

	WebClient webclient;

	g_iCnt = 0;

	CString strHtml;

	//请求12306的图片为例

	webclient.Get(_T("https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.7099142521619793"), strHtml,g_iCnt);

  

你可能感兴趣的:(https)