动态分配内存,用于存储使用 WinHttpReadData 下载的 HTML 源代码
Dynamically allocate memory for storage of HTML source downloaded with WinHttpReadData
首先,字符串不能使用,这是一个要求。
我正在尝试实现Winhttp以便从HTTP下载内容。我使用了MSDN上提供的示例(http://msdn.microsoft.com/en-us/library/windows/desktop/aa384270(v=vs.85).aspx)。
我确定你们中的一些人知道WinHttpReadData()将数据读取到临时缓冲区中,而不是写入现有数据,直到请求完成。如果您只是想每次打印出缓冲区,这很好,但是,我需要将整个响应存储到缓冲区中以供以后使用。
为此,我创建了一个结构,其中包含执行请求所需的所有"事物",我通过引用执行请求的函数来传递此结构。 结构如下:
struct HttpG
{
wchar_t* wszUserAgent;
wchar_t* wszCookie;
wchar_t* wszHost;
wchar_t* wszPath;
char* szResponse;
};
执行请求的函数定义如下:
int HttpGet(HttpG &http_get);
目前为止,一切都好。。。。
现在,当我尝试为http_get.szResponse动态分配内存时,问题就出现了。 并非所有数据都被读取。我不打算发布来自 MSDN 的整个示例代码,但我会发布给我带来问题的部分代码。如果您查看上面的 MSDN 链接,您将看到我指的是代码的哪一部分。这是下载数据的主循环。
// Read the Data.
ZeroMemory(szOutBuffer, dwSize + 1);
if(!WinHttpReadData(hRequest, (LPVOID)szOutBuffer, dwSize, &dwDownloaded))
{
OutputDebugStr("Error in WinHttpReadDatan");
}
else
{
// Read data here
if(http_get.szResponse == NULL)
{
// This part seems to work as needed
http_get.szResponse = new char[dwSize + 1];
ZeroMemory(http_get.szResponse, dwSize + 1);
strcpy(http_get.szResponse, szOutBuffer);
http_get.szResponse[dwSize + 1] = ' ';
}
else
{
// Im sure the problems is here, full source
// is not getting put into http_get.szResponse.
// Create temp buffer
szTemp = new char[strlen(http_get.szResponse) + 1];
ZeroMemory(szTemp, strlen(http_get.szResponse) + 1);
strcat(szTemp, http_get.szResponse);
// Resize origonal buffer to hold new data
http_get.szResponse = new char[strlen(szTemp) + dwSize + 1];
ZeroMemory(http_get.szResponse, strlen(szTemp) + dwSize + 1);
strcpy(http_get.szResponse, szTemp);
strcat(http_get.szResponse, szOutBuffer);
http_get.szResponse[strlen(szTemp) + dwSize + 1] = ' ';
}
}
// Free the memory allocated to the buffer.
delete[] szTemp;
delete[] szOutBuffer;
// This condition should never be reached since WinHttpQueryDataAvailable
// reported that there are bits to read.
if(!dwDownloaded)
{
break;
}
我像这样创建结构并调用函数:
HttpG http_get;
http_get.wszHost = L"au.yahoo.com";
http_get.wszPath = L"/?p=us";
http_get.wszUserAgent = L"Blah blah blah";
http_get.szResponse = NULL;
HttpGet(http_get);
所以基本上在请求结束时,我希望所有数据都在http_get.szResponse中。抱歉,如果这有点混乱/模糊,我试图尽可能地解释它。我做错了什么? 整天都卡在这个上面,任何帮助都非常感谢。
谢谢大家。
您必须在循环中调用WinHttpReadData()
,直到没有更多数据要读取,并且您需要在该循环的每次迭代中动态(重新)分配响应缓冲区。 如果要求禁止您使用std::string
那么它们也可能禁止您使用std::vector
,因此您将不得不求助于手动内存管理,例如:
struct HttpG
{
wchar_t* wszUserAgent;
wchar_t* wszCookie;
wchar_t* wszHost;
wchar_t* wszPath;
u_char* ucResponse;
int ucResponseSize;
};
u_char ucBuffer[1024], *ucTemp;
DWORD dwDownloaded;
do
{
if (!WinHttpReadData(hRequest, ucBuffer, sizeof(ucBuffer), &dwDownloaded))
{
OutputDebugStr("Error in WinHttpReadDatan");
break;
}
if (dwDownloaded == 0)
break;
if (http_get.ucResponse == NULL)
{
http_get.ucResponse = new u_char[dwDownloaded];
memcpy(http_get.ucResponse, ucBuffer, dwDownloaded);
http_get.ucResponseSize = dwDownloaded;
}
else
{
ucTemp = new u_char[http_get.ucResponseSize + dwDownloaded];
memcpy(ucTemp, http_get.ucResponse, http_get.ucResponseSize);
memcpy(&ucTemp[http_get.ucResponseSize], ucBuffer, dwDownloaded);
delete[] http_get.ucResponse;
http_get.ucResponse = ucTemp;
http_get.ucResponseSize += dwDownloaded;
}
}
while (true);
HttpG http_get;
http_get.wszHost = L"au.yahoo.com";
http_get.wszPath = L"/?p=us";
http_get.wszUserAgent = L"Blah blah blah";
http_get.ucResponse = NULL;
http_get.ucResponseSize = 0;
HttpGet(http_get);
// use ucResponse up to ucResponseSize bytes as needed...
delete[] http_get.ucResponse;
即使是你认为正确的代码,也不是。您假设szOutBuffer
以 null 结尾。阅读文档:该&dwDownloaded
参数的存在是有原因的。
在"错误"的代码中,您当然有相同的错误。此外,您泄漏了旧szResponse
(正是因为您没有使用字符串类)。
然后,通过以某种完全错误的方式移动字符串位,使情况变得更糟。似乎您将旧响应附加到空字符串szTemp
(为什么?为什么?),将其复制回新分配的szResponse
,然后附加(仍然大小不正确)szOutBuffer
。
最后,你在szResponse[]
之外写一个