InternetReadFile填充缓冲区,但返回零字节读取

时间:2017-04-07 16:33:51

标签: c++ windows buffer readfile wininet

在尝试从为Windows Compact 2013编写的C ++应用程序中的Internet上下载文件时,我遇到了一个非常奇怪的问题。

BOOL WWW::Read(char* buffer, DWORD buffer_size)
{
    memset(buffer, 0, buffer_size);
    m_dwBytesRead = 0;

    BOOL bResult = InternetReadFile(m_handle, buffer, buffer_size, &m_dwBytesRead);
    if (!bResult)
    {
        DWORD dwLastError = GetLastError();
        TCHAR *err;

        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL, dwLastError,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
            (LPTSTR)&err, 0, NULL))
        {
            LOGMSG(1, (TEXT("InternetReadFile failed at - (%u) %s\r\n"), dwLastError, err));
            LocalFree(err);
        }
    }

    // FUDGE
    if (m_dwBytesRead == 0)
    {
        DWORD dwZeros = countZeros(buffer, buffer_size);
        if (dwZeros < buffer_size)
        {
            m_dwBytesRead = buffer_size;
        }
    }
    // END OF FUDGE

    return bResult;
}

我从另一个成员函数重复调用上面的函数,如下所示

DWORD dwWritten;

while (!(Read(buffer, DOWNLOAD_BUFFER_SIZE) && m_dwBytesRead == 0))
{
    WriteFile(m_hDownload, buffer, m_dwBytesRead, &dwWritten, NULL);
    m_dwActualSize += dwWritten;
    ++m_dwChunks;

    if (m_dwBytesRead > 0)
        m_dwInactivity = 0;
    else if (++m_dwInactivity > INACTIVITY_LIMIT)
        return WDS_INACTIVITY;
}

没有FUDGE,此功能第一次失败,并在后续调用中正常工作。我在第一次通过这个函数调用时得到的错误是

InternetReadFile failed at - (112) There is not enough space on the disk.

我不明白为什么在READ操作期间我应该得到“磁盘上没有足够的空间”错误。我已经检查过缓冲区已分配并且可用,并且与预期大小匹配。实际上,当我检查缓冲区的内容时,我发现它已经填充了预期的字节数,但是m_dwBytesRead变量的内容仍然设置为0。

正如你所看到的,我试图通过检查缓冲区的内容以查看它是否已被填充,然后捏造m_dwBytesRead变量来解决这个特定情况,但这只是一个临时的工作来让我过了这个错误,我真的需要理解为什么会出现这个问题。

这个错误(没有我的软糖)的后果是,数据被丢弃,我最终得到的文件缺少第一个块,但完全正确。因此MD5检查失败,我错过了文件的第一部分。

我碰巧知道文件总是会比我正在使用的块大小大,所以我的软糖会起作用,但我不喜欢在代码中有这些可怕的变通方法,因为它们不需要

如果有人能够解释造成问题的原因,我们将不胜感激。

我正在使用Visual Studio 2013 C ++(本机Windows应用程序,而不是MFC),目标是32位和Unicode,在Windows Compact 2013上运行。

非常感谢, 安德鲁

1 个答案:

答案 0 :(得分:2)

机器实际上是否没有磁盘空间?默认情况下,InternetReadFile会在您的背后写入磁盘:

  

为确保检索所有数据,应用程序必须继续调用InternetReadFile函数,直到函数返回TRUE且lpdwNumberOfBytesRead参数等于零。如果将请求的数据写入高速缓存,则这一点尤为重要,否则将无法正确更新高速缓存,并且不会将下载的文件提交到高速缓存。 请注意,除非打开数据流的原始请求设置INTERNET_FLAG_NO_CACHE_WRITE标记,否则会自动进行缓存。