MFC使用WinHttp实现Http访问

来源:互联网 发布:淘宝店模板制作方法 编辑:程序博客网 时间:2024/06/05 20:52

    最近在做MFC和Java搭建的Web平台进行Http通信,尝试了CUrl方式进行通信,可总是提示各种动态链接库的问题以及程序入口点等问题,也尝试了用CSocket的方式模拟Http进行通信,我发送的消息Java平台可以收到,但是Java平台发送给我的消息,一直在CSocket::OnReceive函数中接收不到:这个函数有响应,说明Java平台有数据发送过来,但是Receive函数中接受的数据是空,猜测是Java端和MFC端的字符格式不一样,需要进行一定的转换。最后尝试了WinHttp的方式,终于将问题解决了。以下是相应代码代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include "stdafx.h"#include <afx.h>#include <vector>#include <winhttp.h>#pragma comment(lib,"winhttp.lib")int  SplitString(CString str_in, CString chSplit_in,BOOL bAllowNullString,std::vector<CString>& data)   //将输入字符串按照指定分隔符进行分割{   data.clear();str_in.TrimLeft();   str_in.TrimRight();   if(str_in.GetLength()==0)   return 0;    if(chSplit_in.GetLength() == 0)   {   data.push_back(str_in);return 1;   }   CString s;   int n;  do {   n = str_in.Find(chSplit_in);   if(n > 0)   {   data.push_back(str_in.Left(n));str_in = str_in.Right(str_in.GetLength()-n-chSplit_in.GetLength());   str_in.TrimLeft();   }   else if(n==0)   {   if(bAllowNullString)    data.push_back(_T(""));str_in = str_in.Right(str_in.GetLength()-chSplit_in.GetLength());   str_in.TrimLeft();   }   else  {   if((str_in.GetLength()>0)||bAllowNullString)   data.push_back(str_in);break;   }   } while(1); return data.size();   } void GetServerAndObjectName(CString & strServer, CString & strObject,const CString &strUrl)  //通过URL获取主机地址及目标地址 {std::vector<CString> vecTmp1,vecTmp2;SplitString(strUrl,_T("//"),TRUE,vecTmp1);SplitString(vecTmp1.at(1),_T("/"),TRUE,vecTmp2);strServer=vecTmp2.at(0);int sz=vecTmp2.size();for (int i=0;i<sz-2;i++){strObject+=vecTmp2.at(i+1);strObject+=_T("/");}strObject+=vecTmp2.at(sz-1);}BOOL HttpConnectWeb(const CString &strUrl,const CString &strHeaders,const CString &strSend,CString &strRecv,BOOL bPostOrGet) //最主要函数,通信函数{DWORD dwSize = 0,dwDownloaded = 0;LPSTR pszOutBuffer;BOOL  bResults = FALSE;HINTERNET  hSession = NULL, hConnect = NULL,hRequest = NULL;hSession = WinHttpOpen( L"User Agent",WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);   // Use WinHttpOpen to obtain a session handle.CString serverName,objectName;GetServerAndObjectName(serverName,objectName,strUrl);if (hSession)hConnect = WinHttpConnect( hSession,serverName,INTERNET_DEFAULT_HTTP_PORT, 0);  // Specify an HTTP server.CString strPostOrGet;strPostOrGet=(bPostOrGet) ? _T("POST"):_T("GET");if (hConnect)hRequest = WinHttpOpenRequest( hConnect, strPostOrGet, objectName,NULL,WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,0);// Create an HTTP request handle.LPCWSTR header=strHeaders.AllocSysString();SIZE_T len = lstrlenW(header);if( hRequest )bResults = WinHttpAddRequestHeaders( hRequest,header,DWORD(len),WINHTTP_ADDREQ_FLAG_ADD );if (bResults){CStringA strSendData(strSend);int sz=strSendData.GetLength();bResults = WinHttpSendRequest( hRequest,0,0, const_cast<void*>((const void*)(const char*)strSendData), DWORD(sz),DWORD(sz), 0);// Send a request.}if (bResults)bResults = WinHttpReceiveResponse( hRequest, NULL);// End the request.// Keep checking for data until there is nothing left.LPVOID lpOutBuffer = NULL;if (bResults){WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,WINHTTP_HEADER_NAME_BY_INDEX,NULL,&dwSize, WINHTTP_NO_HEADER_INDEX);if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER ){lpOutBuffer = new WCHAR[dwSize/sizeof(WCHAR)];// Allocate memory for the buffer.bResults = WinHttpQueryHeaders( hRequest,WINHTTP_QUERY_RAW_HEADERS_CRLF,WINHTTP_HEADER_NAME_BY_INDEX,lpOutBuffer, &dwSize,WINHTTP_NO_HEADER_INDEX);// Now, use WinHttpQueryHeaders to retrieve the header.}}if (bResults)printf("Header contents: \n%S",lpOutBuffer);// Print the header contents.delete [] lpOutBuffer;// Free the allocated memory.if (!bResults)printf("Error %d has occurred.\n",GetLastError());// Report any errors.if (bResults){do {dwSize = 0;if (!WinHttpQueryDataAvailable( hRequest, &dwSize)) {printf( "Error %u in WinHttpQueryDataAvailable.\n",GetLastError());break;// Check for available data.}if (!dwSize)break;// No more available data.pszOutBuffer = new char[dwSize+1];// Allocate space for the buffer.if (!pszOutBuffer){printf("Out of memory\n");break;}// Read the Data.ZeroMemory(pszOutBuffer, dwSize+1);if (!WinHttpReadData( hRequest, (LPVOID)pszOutBuffer,dwSize, &dwDownloaded)){                                  printf( "Error %u in WinHttpReadData.\n", GetLastError());}elsestrRecv=CString(pszOutBuffer);delete [] pszOutBuffer;// This condition should never be reached since WinHttpQueryDataAvailable// reported that there are bits to read.if (!dwDownloaded)break;} while (dwSize > 0);}else{printf( "Error %d has occurred.\n", GetLastError());// Report any errors.}// Close any open handles.if (hRequest) WinHttpCloseHandle(hRequest);if (hConnect) WinHttpCloseHandle(hConnect);if (hSession) WinHttpCloseHandle(hSession);return TRUE;}</span>

   上述代码在win32 console工程中运行良好,在新建的MFC工程中运行也没有问题,可以把这段代码整合到原来写的一个MFC程序中时,出现了以下问题:

   错误error C2371: “HTTP_VERSION_INFO”: 重定义;不同的基类型 c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winhttp.h ,错误error C2371: “HTTP_VERSION_INFO”: 重定义;不同的基类型 c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winhttp.h ,错误error C2371: “URL_COMPONENTS”: 重定义;不同的基类型 c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winhttp.h 160,错误error C2371: “HTTP_VERSION_INFO”: 重定义;不同的基类型 c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winhttp.h 等问题,这些问题都是同一类问题,多大上百个!在网上查找了很久,最后把问题聚焦在 如下的代码中:

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <winhttp.h>#pragma comment(lib,"winhttp.lib")</span>

    是因为头文件winhttp和原来MFC工程中的一些头文件相冲突,在网上下载了一个修改过得winhttp头文件,改变其的查找方式,问题解决。

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include "winhttp.h"#pragma comment(lib,"winhttp.lib")</span>

    winhttp文件的下载地址:http://download.csdn.net/detail/u014023993/8365593

    WinHttp各种函数见:http://msdn.microsoft.com/en-us/library/windows/desktop/aa384257(v=vs.85).aspx

 




0 0