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

填充的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年

非常感谢, 安德鲁

+0

当你在“常规” Windows上运行它,会发生什么? – Anders

+0

感谢您的建议。我没有在普通的窗户上试过。我当然可以尝试(周一),看看是否有不同的行为。 – pionium

+0

更好的解决方法(如果有效)可能是进行第一次读取,即始终失败的第一次读取,长度为零。 –

是该机器实际上磁盘空间不足? InternetReadFile会写信给你的背后磁盘默认:

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

+0

我不认为有空间问题。它运行的设备有一个500MB的闪存驱动器,其中310MB目前是免费的。但是,您提出了一个非常好的观点,我认为它肯定**值得禁用此操作的缓存,因为这些下载不需要它。感谢您的建议,我一定会尝试这个(周一),看看这是否有所作为。我会让你知道 – pionium

+0

更新:我添加了'INTERNET_FLAG_NO_CACHE_WRITE'标志给'InternetOpenUrl()'调用,但遗憾的是没有任何区别。我仍然收到“磁盘空间不足”的错误。暂时我坚持我的工作。如果我发现一个解决方案,我会回到这里。 – pionium

+0

验证代码在“正常”Windows上运行后,我会建议您调试该函数或与Microsoft联系... – Anders