0

我对WinInet 的 InternetReadFile (C++) 有疑问。
在极少数情况下,函数会失败,GetLastError 返回上述错误0x8007007a(根据 ErrorLookup 对应于“传递给系统调用的数据区域太小”)。

我对此有几个问题:

  1. 为什么在极少数情况下会发生这种情况,但在其他情况下却可以正常工作(我当然是在谈论总是下载相同的 ~15MB zip 文件)?
  2. 这真的与传递给 API 调用的缓冲区大小有关吗?我为此调用使用了 1024 BYTES 的 const 缓冲区大小。我应该使用更大的缓冲区大小吗?如果是这样,我怎么知道“正确”的缓冲区大小是多少?
  3. 如果我确实收到此错误,我该怎么做才能在运行时恢复?

添加代码片段(请注意,这不会按原样工作,因为需要一些初始化代码):

#define HTTP_RESPONSE_BUFFER_SIZE 1024
std::vector<char> responseBuffer;
DWORD dwResponseBytesRead = 0;

do
{
    const size_t oldBufferSize = responseBuffer.size();
    responseBuffer.resize(oldBufferSize + HTTP_RESPONSE_BUFFER_SIZE);

    // Now we read again to the last place we stopped
    // writing in the previous iteration.
    dwResponseBytesRead = 0;
    BOOL bInternetReadFile = ::InternetReadFile(hOpenRequest, // hFile. Retrieved from a previous call to ::HttpOpenRequest
        (LPVOID)&responseBuffer[oldBufferSize], // lpBuffer.
        HTTP_RESPONSE_BUFFER_SIZE, // dwNumberOfBytesToRead.
        &dwResponseBytesRead); // lpdwNumberOfBytesRead.

    if(!bInternetReadFile)
    {
        // Do clean up and exit.
        DWORD dwErr = ::GetLastError(); // This, in some cases, will return: 0x7a 
        HRESULT hr = HRESULT_FROM_WIN32(dwErr); // This, in some cases, will return: 0x8007007a
        return;
    }

    // Adjust the buffer according to the actual number of bytes read.
    responseBuffer.resize(oldBufferSize + dwResponseBytesRead);
}
while(dwResponseBytesRead != 0);
4

1 回答 1

3

这是 InternetReadFile 的记录错误:

WinINet 尝试一次将 HTML 写入 lpBuffer 缓冲区一行。如果应用程序的缓冲区太小而无法容纳至少一行生成的 HTML,则会返回错误代码 ERROR_INSUFFICIENT_BUFFER 作为应用程序需要更大缓冲区的指示。

所以你应该通过增加缓冲区大小来处理这个错误。只需将大小翻倍,如有必要可重复。

存在一些差异。不清楚您正在阅读一个 HTML 文件,15MB 似乎过多。另一个是这个错误应该很好地重复。但最麻烦的是错误代码值,它被包装在 HRESULT 中,即 COM 组件将返回的那种错误代码。您应该从 GetLastError() 得到一个 Windows 错误代码,只是 0x7a 而不是 0x8007007a。

请确保您的错误检查是正确的。仅当 InternetReadFile() 返回 FALSE 时才调用 GetLastError()。如果检查出来(请务必发布一个片段),那么请考虑这个错误实际上是在上游生成的,可能是防火墙或易碎的反恶意软件。

于 2013-08-15T08:44:41.430 回答