c++ - InternetReadFile 填充缓冲区,但返回读取的零字节

标签 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.

我不明白为什么在读取操作期间会出现“磁盘空间不足”错误。我已检查缓冲区是否已分配且可用,并且是否符合预期大小。事实上,当我检查缓冲区的内容时,我发现它已填充了预期的字节数,但是 m_dwBytesRead 变量的内容仍然设置为 0。

正如您所看到的,我尝试通过检查缓冲区的内容以查看它是否已被填充,然后捏造 m_dwBytesRead 变量来围绕这种特定情况进行编码,但这只是一个临时解决办法经过这个错误,我真的需要理解为什么会出现这个问题。

这个错误的后果(没有我的胡言乱语)是数据被丢弃,我最终得到的文件缺少第一个 block ,但在其他方面完全正确。因此 MD5 检查失败,并且我丢失了文件的第一部分。

我只是碰巧知道该文件总是大于我正在使用的 block 大小,所以我的软糖会起作用,但我不喜欢在不需要这些可怕的解决方法时在代码中使用这些可怕的解决方法.

如果有人能够阐明导致问题的原因,我们将不胜感激。

我使用的是 Visual Studio 2013 C++( native Windows 应用,不是 MFC),目标是 32 位和 Unicode,在 Windows Compact 2013 上运行。

非常感谢, 安德鲁

最佳答案

机器实际上磁盘空间不足吗?默认情况下,InternetReadFile 将在您背后写入磁盘:

To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero. This is especially important if the requested data is written to the cache, because otherwise the cache will not be properly updated and the file downloaded will not be committed to the cache. Note that caching happens automatically unless the original request to open the data stream set the INTERNET_FLAG_NO_CACHE_WRITE flag.

关于c++ - InternetReadFile 填充缓冲区,但返回读取的零字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43283091/

相关文章:

c++ - 是什么导致了我的错误?我正在尝试创建一个玩家类并将玩家名称存储为变量

windows - 在 windows 7 中运行 aero 时强制单个应用程序使用 windows 经典主题

c - 如何使用 fgets/read/fread 识别 double\n\n

c++ - 数据长度过大的解压缓冲区会崩溃

Java StringBuffer 工作正常,reverse() 添加换行符

c++ - Lua shutdown double free,lua线程在关闭期间还活着吗?

C++11 特性检查

Windows 资源管理器备用数据流外壳扩展

c++ - 禁用 Visual Studio 消息

windows - 无效 ID : Process leaked file descriptors. Jenkins