C++ C++;WinHttp获取响应头和响应体
我目前正在尝试编写一个类,使发送简单请求变得更容易。C++ C++;WinHttp获取响应头和响应体,c++,winapi,httprequest,httpresponse,winhttp,C++,Winapi,Httprequest,Httpresponse,Winhttp,我目前正在尝试编写一个类,使发送简单请求变得更容易。 最后,我希望它可以像这样使用: int _tmain(int argc, _TCHAR* argv[]) { HttpRequest Request(L"Example UserAgent/1.0",L"",L""); Request.SendRequest(L"google.com",L"GET",NULL); if (Request.responseHeader) printf("%s",Reque
最后,我希望它可以像这样使用:
int _tmain(int argc, _TCHAR* argv[])
{
HttpRequest Request(L"Example UserAgent/1.0",L"",L"");
Request.SendRequest(L"google.com",L"GET",NULL);
if (Request.responseHeader)
printf("%s",Request.responseHeader);
if (Request.responseBody)
printf("%s",Request.responseBody);
getchar();
return 0;
}
但现在它根本不起作用。我不知道如何获取响应头,我无法将响应头写入我的类的公共成员。是的,我对C++非常的不好,尤其是关于WiAPI的。 我希望你能帮助我。
以下是我目前的代码:
#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
class HttpRequest {
private:
DWORD dwSize;
DWORD dwDownloaded;
LPSTR pszOutBuffer;
BOOL bResults;
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
LPCWSTR _userAgent;
//LPCWSTR _proxyIp;
//LPCWSTR _proxyPort;
size_t bodySize;
public:
HttpRequest(LPCWSTR, LPCWSTR, LPCWSTR);
void SendRequest(LPCWSTR, LPCWSTR, LPVOID);
LPSTR responseHeader[1000000];
LPSTR responseBody[1000000];
};
HttpRequest::HttpRequest(LPCWSTR userAgent, LPCWSTR proxyIp, LPCWSTR proxyPort) {
_userAgent = userAgent;
//_proxyIp = proxyIp;
//_proxyPort = proxyPort;
hSession = WinHttpOpen( userAgent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
}
void HttpRequest::SendRequest(LPCWSTR url, LPCWSTR method, LPVOID body) {
bodySize = 0;
if (hSession)
hConnect = WinHttpConnect( hSession, url, INTERNET_DEFAULT_HTTPS_PORT, 0 );
else
printf("session handle failed\n");
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, method, NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
else
printf("connect handle failed\n");
if (hRequest)
bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, 0, 0, 0 );
else
printf("request handle failed\n");
if( bResults )
bResults = WinHttpReceiveResponse( hRequest, NULL );
if( bResults )
{
do
{
// Check for available data.
dwSize = 0;
if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
printf( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) );
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize+1];
if( !pszOutBuffer )
{
printf( "Out of memory\n" );
dwSize=0;
}
else
{
// Read the data.
ZeroMemory( pszOutBuffer, dwSize+1 );
if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded ) )
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
else {
//printf( "%s", pszOutBuffer );
responseBody[bodySize++] = pszOutBuffer;
}
// Free the memory allocated to the buffer.
delete [] pszOutBuffer;
}
} while( dwSize > 0 );
}
// Report any errors.
if( !bResults )
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
}
#包括“stdafx.h”
#包括
#包括
#pragma注释(lib,“winhttp.lib”)
类HttpRequest{
私人:
DWORD dwSize;
德沃德·德沃德;
LPSTR-pszOutBuffer;
布尔结果;
腹地会话;
腹地连接;
腹地探索;
LPCWSTR_用户代理;
//LPCWSTR_proxyIp;
//LPCWSTR\u代理端口;
大小与体型;
公众:
HttpRequest(LPCWSTR,LPCWSTR,LPCWSTR);
无效发送请求(LPCWSTR、LPCWSTR、LPVOID);
LPSTR负责人[1000000];
LPSTR响应库[1000000];
};
HttpRequest::HttpRequest(LPCWSTR用户代理、LPCWSTR代理、LPCWSTR代理){
_userAgent=userAgent;
//_proxyIp=proxyIp;
//_proxyPort=proxyPort;
hsSession=WinHttpOpen(用户代理、WINHTTP\u访问类型、默认代理、WINHTTP\u无代理、WINHTTP\u无代理、0);
}
void HttpRequest::SendRequest(LPCWSTR url、LPCWSTR方法、LPVOID正文){
体型=0;
如果(hsSession)
hConnect=WinHttpConnect(会话、url、INTERNET\u默认\u HTTPS\u端口,0);
其他的
printf(“会话句柄失败\n”);
如果(hConnect)
hRequest=WinHttpOpenRequest(hConnect,method,NULL,NULL,WINHTTP\u NO\u REFERER,WINHTTP\u DEFAULT\u ACCEPT\u type,WINHTTP\u FLAG\u SECURE);
其他的
printf(“连接句柄失败\n”);
如果(hRequest)
bResults=WinHttpSendRequest(hRequest,WINHTTP_无附加_头,0,正文,0,0);
其他的
printf(“请求句柄失败\n”);
如果(b结果)
bResults=WinHttpReceiveResponse(hRequest,NULL);
如果(b结果)
{
做
{
//检查可用数据。
dwSize=0;
如果(!WinHttpQueryDataAvailable(hRequest和dwSize))
printf(“WinHttpQueryDataAvailable中的错误%u。\n”,GetLastError());
//为缓冲区分配空间。
pszOutBuffer=新字符[dwSize+1];
如果(!pszOutBuffer)
{
printf(“内存不足\n”);
dwSize=0;
}
其他的
{
//读取数据。
零内存(pszOutBuffer,dwSize+1);
if(!WinHttpReadData(hRequest,(LPVOID)pszOutBuffer、dwSize和dwDownloaded))
printf(“WinHttpReadData中的错误%u。\n”,GetLastError());
否则{
//printf(“%s”,pszOutBuffer);
responseBody[bodySize++]=pszOutBuffer;
}
//释放分配给缓冲区的内存。
删除[]pszOutBuffer;
}
}而(dwSize>0);
}
//报告任何错误。
如果(!bResults)
printf(“发生了错误%d。\n”,GetLastError());
//关闭所有打开的手柄。
if(hRequest)WinHttpCloseHandle(hRequest);
if(hConnect)WinHttpCloseHandle(hConnect);
if(hSession)WinHttpCloseHandle(hSession);
}
用于访问响应标题。使用WINHTTP\u QUERY\u RAW\u头(\u CRLF)
标志指定要检索所有可用头
您还需要更改类以动态分配其responseHeader
和responseBody
成员。使用静态数组不仅浪费了大量内存,而且限制了可以处理的响应大小
试试这个:
#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <vector>
#pragma comment(lib, "winhttp.lib")
class HttpRequest
{
private:
std::wstring _userAgent;
//std::wstring _proxyIp;
//std::wstring _proxyPort;
public:
HttpRequest(const std::wstring&, const std::wstring&, const std::wstring&);
bool SendRequest(const std::wstring&, const std::wstring&, void*, DWORD);
std::wstring responseHeader;
std::vector<BYTE> responseBody;
};
HttpRequest::HttpRequest(const std::wstring &userAgent, const std::wstring &proxyIp, const std::wstring &proxyPort) :
_userAgent(userAgent)
//,_proxyIp(proxyIp)
//,_proxyPort(proxyPort)
{
}
bool HttpRequest::SendRequest(const std::wstring &url, const std::wstring &method, void *body, DWORD bodySize)
{
DWORD dwSize;
DWORD dwDownloaded;
DWORD headerSize = 0;
BOOL bResults = FALSE;
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
responseHeader.resize(0);
responseBody.resize(0);
hSession = WinHttpOpen( _userAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
if (hSession)
hConnect = WinHttpConnect( hSession, url.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0 );
else
printf("session handle failed\n");
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, method.c_str(), NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
else
printf("connect handle failed\n");
if (hRequest)
bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, bodySize, 0, 0 );
else
printf("request handle failed\n");
if (bResults)
bResults = WinHttpReceiveResponse( hRequest, NULL );
if (bResults)
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, WINHTTP_NO_OUTPUT_BUFFER, &headerSize, WINHTTP_NO_HEADER_INDEX);
if ((!bResults) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
responseHeader.resize(headerSize / sizeof(wchar_t));
if (responseHeader.empty())
{
bResults = TRUE;
}
else
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, &responseHeader[0], &headerSize, WINHTTP_NO_HEADER_INDEX);
if( !bResults ) headerSize = 0;
responseHeader.resize(headerSize / sizeof(wchar_t));
}
}
}
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
bResults = WinHttpQueryDataAvailable( hRequest, &dwSize );
if (!bResults)
{
printf( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) );
break;
}
if (dwSize == 0)
break;
do
{
// Allocate space for the buffer.
DWORD dwOffset = responseBody.size();
responseBody.resize(dwOffset+dwSize);
// Read the data.
bResults = WinHttpReadData( hRequest, &responseBody[dwOffset], dwSize, &dwDownloaded );
if (!bResults)
{
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
dwDownloaded = 0;
}
responseBody.resize(dwOffset+dwDownloaded);
if (dwDownloaded == 0)
break;
dwSize -= dwDownloaded;
}
while (dwSize > 0);
}
while (true);
}
// Report any errors.
if (!bResults)
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
return bResults;
}
用于访问响应标题。使用WINHTTP\u QUERY\u RAW\u头(\u CRLF)
标志指定要检索所有可用头
您还需要更改类以动态分配其responseHeader
和responseBody
成员。使用静态数组不仅浪费了大量内存,而且限制了可以处理的响应大小
试试这个:
#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <vector>
#pragma comment(lib, "winhttp.lib")
class HttpRequest
{
private:
std::wstring _userAgent;
//std::wstring _proxyIp;
//std::wstring _proxyPort;
public:
HttpRequest(const std::wstring&, const std::wstring&, const std::wstring&);
bool SendRequest(const std::wstring&, const std::wstring&, void*, DWORD);
std::wstring responseHeader;
std::vector<BYTE> responseBody;
};
HttpRequest::HttpRequest(const std::wstring &userAgent, const std::wstring &proxyIp, const std::wstring &proxyPort) :
_userAgent(userAgent)
//,_proxyIp(proxyIp)
//,_proxyPort(proxyPort)
{
}
bool HttpRequest::SendRequest(const std::wstring &url, const std::wstring &method, void *body, DWORD bodySize)
{
DWORD dwSize;
DWORD dwDownloaded;
DWORD headerSize = 0;
BOOL bResults = FALSE;
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
responseHeader.resize(0);
responseBody.resize(0);
hSession = WinHttpOpen( _userAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
if (hSession)
hConnect = WinHttpConnect( hSession, url.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0 );
else
printf("session handle failed\n");
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, method.c_str(), NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
else
printf("connect handle failed\n");
if (hRequest)
bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, bodySize, 0, 0 );
else
printf("request handle failed\n");
if (bResults)
bResults = WinHttpReceiveResponse( hRequest, NULL );
if (bResults)
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, WINHTTP_NO_OUTPUT_BUFFER, &headerSize, WINHTTP_NO_HEADER_INDEX);
if ((!bResults) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
responseHeader.resize(headerSize / sizeof(wchar_t));
if (responseHeader.empty())
{
bResults = TRUE;
}
else
{
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, &responseHeader[0], &headerSize, WINHTTP_NO_HEADER_INDEX);
if( !bResults ) headerSize = 0;
responseHeader.resize(headerSize / sizeof(wchar_t));
}
}
}
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
bResults = WinHttpQueryDataAvailable( hRequest, &dwSize );
if (!bResults)
{
printf( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) );
break;
}
if (dwSize == 0)
break;
do
{
// Allocate space for the buffer.
DWORD dwOffset = responseBody.size();
responseBody.resize(dwOffset+dwSize);
// Read the data.
bResults = WinHttpReadData( hRequest, &responseBody[dwOffset], dwSize, &dwDownloaded );
if (!bResults)
{
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
dwDownloaded = 0;
}
responseBody.resize(dwOffset+dwDownloaded);
if (dwDownloaded == 0)
break;
dwSize -= dwDownloaded;
}
while (dwSize > 0);
}
while (true);
}
// Report any errors.
if (!bResults)
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
return bResults;
}
非常感谢。不过向量似乎有问题。我从未使用过向量,我不确定我是否理解它们。我得到以下错误:调试断言失败文件:c:\program files(x86)\microsoft visual studio 10.0\vc\include\vector |行:932 |表达式:矢量下标超出范围。。。我还想知道如何获得请求正文的字节大小,以及是否可以在函数中计算它。这是修改后的版本:请求和响应被正确发送,应用程序只是因为向量而失败…当我尝试它时,工作正常,没有超出范围的错误。不过,我已经为您调整了代码,以防万一。当
SendRequest()
返回true时,您可以通过responseBody.size()
检索正文大小。并非总是能够提前获得正文大小,例如,当使用HTTP的传输编码:chunked
头时。所以你只要一直读到回应的结尾,我不明白,为什么只有我会得到这个错误。这怎么可能?我会做错什么?这就是调试器的作用。我以前从未使用过向量。我完全不知道它们是如何工作的。[…]如果(size(),谢谢。但向量似乎有问题。我从未使用过向量,也不确定是否理解它们。我收到以下错误:调试断言失败!|文件:c:\program files(x86)\microsoft visual studio 10.0\vc\include\vector | Line:932 |表达式:向量下标超出范围…我还想知道如何获得请求正文的字节大小,以及是否可以在函数中计算它。H