基于Windows的 wininet 网络库 写的访问服务器接口的函数

今天分享下 关于网络的代码   在windows平台下 基于 wininet 网络库  以HTTP / HTTPS 访问 服务器的接口

很多人开发  都卡在了这一步

#include <WinInet.h> // 加载 网络模块
#pragma comment(lib,"Wininet.lib")
#include "tinystr.h"  // 加载解析XML模块
#include "tinyxml.h"
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <atlstr.h>
#include <string>
#include "md5.h"
using namespace std;
// 网络地址   IP 或者 网址  网址不要加 http://  直接www
#ifdef UNICDOE
wchar_t *g_strUrl2 = L"10.110.110.100";
#else 
char *g_strUrl2 = "<span style="font-family: Arial, Helvetica, sans-serif;">10.110.110.100</span>";
#endif
int g_nPort = 8080;  // 网络链接 端口
string g_strCurVersion = "1.0.27";  // 当前版本号   这个可以写到 资源里/配置文件里/注册表里 等  我这里为了方便写在了全局变量
typedef struct UpdateInfoParam
{
	string strVersion;
	string strUrl;
	string strPath;
	string strName;
	string strMd5;
	string strSize;
	string strLog;
}UpdateInfo;
// UTF8 ----- UNICODE 转码
CString UTF8toUnicode(LPCSTR pszStr)
{
	if (!pszStr)
		return _T("");

	//预转换,计算需要的空间
	int wstrlen = ::MultiByteToWideChar(CP_UTF8, NULL, pszStr, strlen(pszStr), NULL, 0);
	if( wstrlen == 0 )
	{
		return  CString(_T(""));
	}
	++wstrlen;
	WCHAR *wp = new WCHAR[wstrlen];
	::ZeroMemory(wp, (wstrlen)*sizeof(WCHAR));
	//转换
	int ret = ::MultiByteToWideChar(CP_UTF8, NULL, pszStr, strlen(pszStr), wp, wstrlen);
	if( ret != 0 )
	{
		CString s = wp ;
		delete[] wp ;
		return s ;
	}
	//保存并返回
	delete[] wp ;
	return CString(_T("")); ;
}



// 这个方法 是 集  网络请求 XML 解析 于一体  把XML解析出来的结果 保存到了 g_UpdateInfo 结构体里面
int UpdateModuleMethod()
{
HINTERNET hSession = NULL;  //  WININET 回话句柄
HINTERNET hConnect = NULL;// WININET 链接句柄
HINTERNET hRequest = NULL;// WININET 请求句柄
INTERNET_BUFFERS g_hNetBuf;
char *psz =NULL;
//string strXmluni="";  // XMLsh  


TCHAR szFilePath[MAX_PATH];
//  访问网页的XML
hSession = InternetOpenA("UpdateModule",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
assert(hSession != NULL);
hConnect = InternetConnectA(hSession,g_strUrl2,g_nPort,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);
assert(hConnect != NULL);
DWORD dwOpenRequestFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | 
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | 
INTERNET_FLAG_KEEP_CONNECTION | 
INTERNET_FLAG_NO_AUTH | 
INTERNET_FLAG_NO_AUTO_REDIRECT | 
INTERNET_FLAG_NO_COOKIES | 
INTERNET_FLAG_NO_UI | 
INTERNET_FLAG_RELOAD; 


const char *pStr = "hxsp/update/admin/ver.xml";
hRequest = HttpOpenRequestA(hConnect,"GET",pStr,"HTTP/1.1",NULL,NULL,dwOpenRequestFlags,0);


if (hRequest != NULL)
{
if(!HttpSendRequestA(hRequest,NULL,0,NULL,0))  // 链接超时 
{
return 0;
}
}
char szBuffer[2048] = {0};
DWORD dwLen = 2048;
HttpQueryInfoA(hRequest,HTTP_QUERY_STATUS_CODE,szBuffer,&dwLen,NULL);
if (strcmp(szBuffer,"200") != 0)  // 服务器未响应
{
if (strcmp(szBuffer,"404") == 0)
{
MessageBox(NULL,L"网络异常",L"网络提示",MB_OK);
exit(0);
}
return 1;
}
else    // 网络请求正常  进行下面的代码
{
DWORD dwInforLevel = HTTP_QUERY_RAW_HEADERS_CRLF;
DWORD dwInfoBufferLength = 10;
char *pInfoBuffer = (char *)malloc(dwInfoBufferLength+1);
while (!HttpQueryInfoA(hRequest,dwInforLevel,pInfoBuffer,&dwInfoBufferLength,NULL))
{
DWORD dwErr = GetLastError();
if (dwErr == ERROR_INSUFFICIENT_BUFFER)     
{   
free(pInfoBuffer);         
pInfoBuffer = (char *)malloc(dwInfoBufferLength+1);   
}
}
pInfoBuffer[dwInfoBufferLength] = '\n\r\0';
char *str = pInfoBuffer;
free(pInfoBuffer);


DWORD dwBytesAvailble;
if(InternetQueryDataAvailable(hRequest,&dwBytesAvailble,0,0))    // 读取 服务器 返回数据
{
dwBytesAvailble = dwBytesAvailble + (4597 - dwBytesAvailble);
char *pMessageBody = (char *)malloc(dwBytesAvailble);
memset(pMessageBody,0,dwBytesAvailble);
DWORD dwBytesRead;
BOOL bResult = InternetReadFile(hRequest,pMessageBody,dwBytesAvailble,&dwBytesRead);     // 保存服务器返回数据
CString strXml = UTF8toUnicode(pMessageBody);
psz = (char *)malloc(strlen(pMessageBody)+1);
strcpy(psz,pMessageBody);
char *pCurDir;
int nLen = WideCharToMultiByte(CP_ACP,0,strXml,-1,NULL,0,NULL,NULL); 
int i = (int)wcslen(strXml)*sizeof(TCHAR); 
pCurDir = new char[i+1]; 
if (!pCurDir) // 如果申请内存失败 重新再申请一次
{ 
pCurDir = new char[i+1];
} 
if(!pCurDir) { return 0; } 
WideCharToMultiByte(CP_ACP,0,strXml,-1,pCurDir,nLen,NULL,NULL);
CStringA strXmlA(strXml.GetBuffer());
string strXmluni = strXmlA.GetBuffer(0);
}
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);  //  关闭 网络请求句柄  防止内存泄露
hSession = hConnect = hRequest = NULL;  // 句柄清零


// 解析XML
CString strXml = UTF8toUnicode(psz);
CStringA strXmlA(strXml.GetBuffer());
string strXmluni = strXmlA.GetBuffer(0);
TiXmlDocument *myDocument = new TiXmlDocument();
myDocument->Parse(strXmluni.c_str(),0,TIXML_ENCODING_LEGACY);
TiXmlElement *RootElement  = myDocument->RootElement();
while(RootElement)
{
TiXmlElement *pTaskGroup1 = RootElement->FirstChildElement();


while(pTaskGroup1)
{
if (pTaskGroup1->GetText() !=NULL)
{
//std::cout << pTaskGroup1->Value()<< " : " << pTaskGroup1->GetText() << std::endl;
if (strcmp(pTaskGroup1->Value(),"ver")==0)
{
g_UpdateInfo.strVersion = pTaskGroup1->GetText();
}
else if(strcmp(pTaskGroup1->Value(),"url")==0)
{
g_UpdateInfo.strUrl = pTaskGroup1->GetText();
}
else if(strcmp(pTaskGroup1->Value(),"log")==0)
{
g_UpdateInfo.strLog = pTaskGroup1->GetText();
}
}
if (strcmp(pTaskGroup1->Value(),"download")==0)
{
TiXmlElement *pTaskChildGroup = pTaskGroup1->FirstChildElement();
while(pTaskChildGroup)
{
if (strcmp(pTaskChildGroup->Value(),"file")==0)
{
TiXmlElement *pTaskChildGroup2 = pTaskChildGroup->FirstChildElement();
while (pTaskChildGroup2)
{
if (strcmp(pTaskChildGroup2->Value(),"path")==0)
{
g_UpdateInfo.strPath = pTaskChildGroup2->GetText();
}
else if(strcmp(pTaskChildGroup2->Value(),"name")==0)
{
g_UpdateInfo.strName = pTaskChildGroup2->GetText();
}
else if (strcmp(pTaskChildGroup2->Value(),"md5")==0)
{
g_UpdateInfo.strMd5 = pTaskChildGroup2->GetText();
}
else if (strcmp(pTaskChildGroup2->Value(),"size")==0)
{
g_UpdateInfo.strSize = pTaskChildGroup2->GetText();
}
pTaskChildGroup2 = pTaskChildGroup2->NextSiblingElement();
}
}
pTaskChildGroup = pTaskChildGroup->NextSiblingElement();
}
}
pTaskGroup1 = pTaskGroup1->NextSiblingElement();
}
RootElement = RootElement->NextSiblingElement();
}
return 0;
}


 
 

int _tmain(int argc, _TCHAR* argv[])
{
	int n = GetTickCount();
	UpdateModuleMethod();  // 调用 网络请求函数
	int m = GetTickCount();
	int nRes = m - n ;   // nRes 结果是 运行这段 访问网络请求代码 所消耗的 毫秒数

	if (strcmp(g_UpdateInfo.strVersion.c_str(),g_strCurVersion.c_str())==0) // 如果本地版本 和 服务器版本一直 则不更新
	{
		MessageBox(0,L"已经是最新版本",L"更新提示",MB_OK);
	}
	else
	{
		// 打开本地的 要更新的文件
		const char *fileName="D:\\hxsp.exe";
 		HANDLE hFile =CreateFileA(fileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
 		DWORD dwReadSize = 0;
		DWORD filesize = GetFileSize(hFile, NULL);
		char *buffer = new char[filesize+1];  
 		ReadFile(hFile,buffer,filesize,&dwReadSize,NULL);
		CloseHandle(hFile);
		MD5 iMD5;
		iMD5.GenerateMD5(buffer, filesize);
		string result = iMD5.ToString();    // 本地文件的MD5值
		delete []buffer;
		if(strcmp(g_UpdateInfo.strMd5.c_str(),result.c_str())==0)
		{
			// 即使 本地版本 和 服务器版本不一致  ,但是 文件的MD5是一致的  所以不更新
		}
		else
		{
			// MD5不一致了  更新文件   更新文件之前 一定要关闭这个文件
			string strDownloadUrl = g_UpdateInfo.strUrl+g_UpdateInfo.strPath+g_UpdateInfo.strName;
			URLDownloadToFileA(0,strDownloadUrl.c_str(),"D:\\hxsp.exe",0,0);
			// 执行到这里 代表更新成功  再对比一次 本地和服务器的MD5值
			const char *fileName="D:\\hxsp.exe";
			HANDLE hFile =CreateFileA(fileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
			DWORD dwReadSize = 0;
			DWORD filesize = GetFileSize(hFile, NULL);
			char *buffer = new char[filesize+1];  
			ReadFile(hFile,buffer,filesize,&dwReadSize,NULL);
			CloseHandle(hFile);
			MD5 iMD5;
			iMD5.GenerateMD5(buffer, filesize);
			string result = iMD5.ToString();    // 本地文件的MD5值
			delete []buffer;
			if(strcmp(g_UpdateInfo.strMd5.c_str(),result.c_str())==0)
			{
				// 如果一致 代表更新成功
				MessageBox(0,L"更新成功",L"更新提示",MB_OK);
			}
		}
		
	}

	return 0;
}


代码是我从很久之前一个工程里 COPY 出来的    可以实现和 HTTP服务器的接口交互

源码下载地址 是:

http://download.csdn.net/detail/innovation_miracle/9411552


接下来我应该有时间 还会写一些 代码分享的文章 

1. 我会分享 我自己 基于WTL 开发写的界面库

2. 基于 Libevent 库的相关使用和说明

3. 软件调试的方法


你可能感兴趣的:(C++,windows,http,网络,WinINet)