一个利用WinInet通信的简单客户端Demo

WinInet简介


         WinInet是微软提供的对Windows客户端与服务器通信的API,它是一个网络编程接口,包含了HTTP、FTP和Gopher,借助于这些接口,开发者不需要了解底层的一些知识,只需要简单的了解HTTP或者FTP协议即可,Gopher慢慢的已经淡出我们的视线,有兴趣的同学可以去找谷歌了解。还有一个微软提供的库WinHttp,主要用于解决服务器和服务器通信。

WinInet的使用方法


      WinInet的一般使用流程:
        (1). 建立连接(InternetOpen、InternetConnect
        (2). 发送请求(HttpOpenRequest 、HttpSendRequest
        (3). 读取接受的数据(InternetReadFile
        (4). 关闭连接(InternetCloseHandle

当然,和服务器通信过程中,肯定会涉及到字符集编码转换,我最近在研究NotePad++的源码,我会整理下它的源码中的关于字符集转换的代码,防止大家重复造轮子。

Http几个重要的通信方式


         1.  GET  从服务器获取URL对应的资源。
         2.  POST 用于修改、注解URL对应的资源。
         3.  PUT 修改或者新建URL对应的资源。
         4.  DELETE 删除URL对应的资源。

HINTERNET HttpOpenRequest(
  _In_  HINTERNET hConnect,
  _In_  LPCTSTR lpszVerb,
  _In_  LPCTSTR lpszObjectName,
  _In_  LPCTSTR lpszVersion,
  _In_  LPCTSTR lpszReferer,
  _In_  LPCTSTR *lplpszAcceptTypes,
  _In_  DWORD dwFlags,
  _In_  DWORD_PTR dwContext
);

HttpOpenRequest的第2个参数 lpszVerb 就是用来指定Http通信方式的,例如:需要指定POST方式,lpszVerb为_T("POST")。

WinInet编程具体例子

1.获取www.baidu.com的网页内容

// TODO: Add extra validation here
 HINTERNET hssetion;
 HINTERNET hConnect;
 HINTERNET hRequrest;
 
 hssetion = InternetOpen( "httpDownload", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
 if ( NULL == hssetion )
 {
  ::AfxMessageBox("open failed");
  return;
 }
 
 hConnect = InternetConnect( hssetion, "www.baidu.com", INTERNET_DEFAULT_HTTP_PORT,
  NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
 if ( NULL == hConnect )
 {
  ::AfxMessageBox("connect failed");
  return;
 }
 
 const char* pFileType = "*/*";
 hRequrest = HttpOpenRequest( hConnect, "GET", "/index.html", "HTTP/1.1", NULL, 
  &pFileType, INTERNET_FLAG_RELOAD, 0 );
 
 if ( NULL == hRequrest )
 {
  ::AfxMessageBox("open requrest failed");
  return;
 }
 
 BOOL bBet = HttpSendRequest( hRequrest, NULL, 0, NULL, 0 );
 if ( !bBet ) 
 {
  ::AfxMessageBox("send request failed");
  return;
 }
 DWORD BufLen=4*1024*10;
 char buffer[4*1024*10] = {0};
 DWORD infoLen=4*1024*10;
 
 DWORD dwIndex=0;
 bool RetQueryInfo=HttpQueryInfo(hRequrest,
  HTTP_QUERY_CONTENT_LENGTH,
  buffer, &infoLen,
  &dwIndex);
 if ( !RetQueryInfo)
 {
  ::AfxMessageBox("query info failed");
  return;
 }
 int FileSize = atoi(buffer); // 文件大小
 
 
 DWORD dwRequest; // 请求下载的字节数
 DWORD dwRead; // 实际读出的字节数
 dwRequest=BufLen;
 
 
 FILE* f = fopen( "Download", "ab" );
 while(true)
 {
  memset( buffer, 0, BufLen );
  bool ReadReturn = InternetReadFile(hRequrest,
   (LPVOID)buffer,
   dwRequest,
   &dwRead);
  if(!ReadReturn)break;
  if(dwRead==0)break;
  // 保存数据
  //  buffer[dwRead]='\0';
  
  //  FileWrite(iFileHandle, buffer, dwRead);
  fwrite( buffer, 1, dwRead, f );
  //  dwCount = dwCount + dwRead;
  // 发出下载进程事件
  
 }


2.提交请求数据

/** POST 参数*/
struct PostParam
{
	string	strResponse; 	// 请求反馈
	TCHAR* 	szObjName;		// 请求资源
	char*	pszPostData;	// post 数据
};

/**
*	@brief 向提交数据
*	@param[in] pServerAddr 服务器地址
*	@param[in] nPort 端口
*	@param[in/out] pParam 服务器提交数据
*	@return -1 请求失败
*	@return 0 成功
*	@date 2013-08-27 10:09:35
*/
int HttpPost(TCHAR* pServerAddr, INTERNET_PORT nPort,PostParam& pParam)
{
	DWORD dwServiceType = INTERNET_SERVICE_HTTP;

	/*wchar_t* szHeaders = L"Content-Type: application/x-www-form-urlencodedn";*/

	// 这个就看服务器怎么定义的
	wchar_t* szHeaders = L"Content-Type: application/json";

	HINTERNET hOpen = NULL; 
	HINTERNET hConnect = NULL;
	HINTERNET hRequest = NULL;  

	hOpen = InternetOpen(TEXT("PervasiveBiz"), INTERNET_OPEN_TYPE_DIRECT,NULL, 0, 0);
	if (!hOpen)
	{
		return -1;
	}

	// 创建连接
	if (!(hConnect = InternetConnect(hOpen, pServerAddr, nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0)))
	{
		InternetCloseHandle(hOpen);
		return -1;
	}

	LPTSTR AcceptTypes[2] = {TEXT("Accept: */*"), NULL};
	DWORD dwFlags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;
	// Open an HTTP request handle. 
	if (!(hRequest = HttpOpenRequest (hConnect, TEXT("POST"), pParam.szObjName, HTTP_VERSION, NULL,NULL /*(LPCTSTR*)AcceptTypes*/, dwFlags, 0)))
	{
		InternetCloseHandle(hConnect);
		InternetCloseHandle(hOpen);
		return -1;
	}

	if(!HttpAddRequestHeaders(hRequest, szHeaders, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE))  
	{
		InternetCloseHandle(hRequest);
		InternetCloseHandle(hConnect);
		InternetCloseHandle(hOpen);
		return -1;
	}

	if(HttpSendRequest(hRequest, NULL, -1,pParam.pszPostData , strlen(pParam.pszPostData)) == FALSE)
	{
		InternetCloseHandle(hRequest);
		InternetCloseHandle(hConnect);
		InternetCloseHandle(hOpen);
		return -1;  
	}

	DWORD dwSize = 0;
	int dwHttpStatus = -1;
	DWORD index = 0;
	LPVOID lpOutBuffer = NULL;

	while (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, (LPVOID)lpOutBuffer, &dwSize, NULL))    
	{
		DWORD dwError = GetLastError();
		if (dwError == ERROR_INSUFFICIENT_BUFFER)
		{
			lpOutBuffer = new wchar_t[dwSize];  
		}
		else
		{
			fprintf(stderr, "HttpQueryInfo failed, error = %d (0x%x)\n",
				GetLastError(), GetLastError());
			break;
		}
	}

	dwHttpStatus = _wtoi((wchar_t*)lpOutBuffer);

	delete lpOutBuffer;
	lpOutBuffer = NULL;

	if ((dwHttpStatus<200)||(dwHttpStatus>300))
	{
		InternetCloseHandle(hRequest);
		InternetCloseHandle(hConnect);
		InternetCloseHandle(hOpen);
		return -1;
	}

	char buffer[1024] = {0}; 
	do   
	{ 
		memset(buffer, 0, 1024);
		if(!InternetReadFile (hRequest, (LPVOID)(buffer),1023, &dwSize))
		{
			InternetCloseHandle(hRequest);
			InternetCloseHandle(hConnect);
			InternetCloseHandle(hOpen);
			return -1; 
		}
		if(dwSize > 0)
		{
			buffer[dwSize] = 0; 
			(pParam.strResponse) += buffer;  
		}

	}while (dwSize != 0); 

	InternetCloseHandle(hRequest);
	InternetCloseHandle(hConnect);
	InternetCloseHandle(hOpen);
	return 0 ;

}


WinInet的bug

1 . 设置各种超时时间不起作用。
      这个bug微软也承认了,但是现在还没有修复,不晓得微软在搞什么鬼。
      http://support.microsoft.com/kb/q176420
2. 有可能会引起crash
这个bug也比较常见,在网上可以搜出很多相关网页。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值