填充的InternetReadFile缓冲,但返回零个字节读取
我有一个很奇怪的问题,同时试图从互联网上下载文件的C++应用程序为Windows编写的紧凑型2013年填充的InternetReadFile缓冲,但返回零个字节读取
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变量来对这个特定情况进行编码,但这只是一个暂时的解决方法,让我通过这个错误,我真的需要明白为什么这个问题正在发生。
这个错误(没有我的诡计)的后果是数据被扔掉了,最后我得到一个缺少第一个块的文件,但是完全正确。因此,MD5检查失败,并且我缺少文件的第一部分。
我只是碰巧知道该文件将总是大于我使用的块大小,所以我的软糖可以工作,但我不喜欢在代码中有这些可怕的解决方法时,他们不应该需要。
如果任何人都可以解释导致问题的原因,将不胜感激。
我使用Visual Studio 2013 C++(原生Windows应用程序,而不是MFC),目标是32位和Unicode,在Windows上运行的紧凑型2013年
非常感谢, 安德鲁
是该机器实际上磁盘空间不足? InternetReadFile
会写信给你的背后磁盘默认:
,以确保所有数据被检索,应用程序必须继续调用函数的InternetReadFile,直到该函数返回TRUE和lpdwNumberOfBytesRead参数等于零。如果请求的数据写入缓存,这一点尤其重要,否则缓存将不会正确更新,并且下载的文件不会提交到缓存。 请注意,缓存会自动发生,除非原始请求打开数据流设置
INTERNET_FLAG_NO_CACHE_WRITE
标记。
我不认为有空间问题。它运行的设备有一个500MB的闪存驱动器,其中310MB目前是免费的。但是,您提出了一个非常好的观点,我认为它肯定**值得禁用此操作的缓存,因为这些下载不需要它。感谢您的建议,我一定会尝试这个(周一),看看这是否有所作为。我会让你知道 – pionium
更新:我添加了'INTERNET_FLAG_NO_CACHE_WRITE'标志给'InternetOpenUrl()'调用,但遗憾的是没有任何区别。我仍然收到“磁盘空间不足”的错误。暂时我坚持我的工作。如果我发现一个解决方案,我会回到这里。 – pionium
验证代码在“正常”Windows上运行后,我会建议您调试该函数或与Microsoft联系... – Anders
当你在“常规” Windows上运行它,会发生什么? – Anders
感谢您的建议。我没有在普通的窗户上试过。我当然可以尝试(周一),看看是否有不同的行为。 – pionium
更好的解决方法(如果有效)可能是进行第一次读取,即始终失败的第一次读取,长度为零。 –