InternetReadFile() 似乎没有读取互联网数据
Posted
技术标签:
【中文标题】InternetReadFile() 似乎没有读取互联网数据【英文标题】:InternetReadFile() does not seem to read internet data 【发布时间】:2013-01-21 19:49:54 【问题描述】:我是这里网站的新人,如果我在这篇文章中做错了什么,请原谅我。
我正在使用WinINet
并尝试从互联网上下载binary file
,但由于某种原因,当我使用InternetReadFile()
实际下载该文件时,它返回的内容根本没有读取( 0 字节信息读取)。运行Visual Studio 2012 debugger
向我揭示了这个细节,因为我提供给API 调用的HINTERNET
处理程序肯定有数据。我只是不明白我做错了什么。也许你们可以帮忙?
我的程序的基本要点是我从网上下载一个二进制文件,并将其保存到一个临时目录中的临时文件中。将内容复制到临时文件后,我将该临时文件的二进制数据内容传输到另一个本地文件(这次在有效目录中)。这是我到目前为止所拥有的。希望通过我提供的逻辑分解,尽管代码很长,你们仍然能够遵循它......
#include "httpfileretrieval.h" // contains all handlers (hInstance, etc.)
bool downloadFile(const char* lpszServer, const char* lpszUrl, const char* destPath)
FILE *tempFile = NULL;
FILE *localFile = NULL;
const int bufsize = 4096;
DWORD tempDirBytes;
DWORD dwSize = 4096; // experiment - ignore the fact this is the same as bufsize
DWORD dwRead = 0;
char lpszDataBuffer[bufsize];
lpszDataBuffer[bufsize] = '\0';
char tempPath[MAX_PATH];
char tempFileName[bufsize]; // will hold the FULL temp file path
std::string srcPath;
srcPath.append(lpszServer);
srcPath.append(lpszUrl); // http://www.domain.com/url into srcPath
hInstance = InternetOpen("httpfret",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
INTERNET_FLAG_ASYNC); // ASYNC Flag
if (!hInstance)
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetOpen Failed! Windows Error %d\n", errorNum);
return false;
// Setup callback function due to INTERNET_FLAG_ASYNC
if (InternetSetStatusCallback(hInstance,(INTERNET_STATUS_CALLBACK)&Callback)
== INTERNET_INVALID_STATUS_CALLBACK)
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetSetStatusCallback Failed! Windows Error %d\n", errorNum);
return false;
// First call that will actually complete asynchronously even though
// there is no network traffic
hConnect = InternetConnect(hInstance,
lpszServer,
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,hg
INTERNET_SERVICE_HTTP,
0,
1); // Connection handle's Context
if (!hConnect)
if (GetLastError() != ERROR_IO_PENDING)
DWORD errorNum = GetLastError();
fprintf(stderr, "InternetConnect Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hInstance);
return false;
// Wait until we get the connection handle
WaitForSingleObject(hConnectedEvent, INFINITE);
// Open the request
hRequest = HttpOpenRequest(hConnect, "GET", lpszUrl, NULL, NULL, NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
2); // Request handle's context
if (!hRequest)
if (GetLastError() != ERROR_IO_PENDING)
DWORD errorNum = GetLastError();
fprintf(stderr, "HttpOpenRequest Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);h
return false;
// Wait until we get the request handle
WaitForSingleObject(hRequestOpenedEvent, INFINITE);
// Send the request
if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
if (GetLastError() != ERROR_IO_PENDING)
DWORD errorNum = GetLastError();
fprintf(stderr, "HttpSendRequest Failed! Windows Error %d\n", errorNum);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
if (bVerbose)
printf("HttpSendRequest called successfully\n");
WaitForSingleObject(hRequestCompleteEvent, INFINITE);
// Before downloading file...
// 1. Get the temp directory
if (!(tempDirBytes = GetTempPathA(MAX_PATH, tempPath)))
fprintf(stderr, "Could not get temporary directory\n");
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
// 2. Get temp file name (full name: tempPath\temp.tmp)
srand(GetTickCount());
sprintf(tempFileName, "%s\\%08X.tmp", tempPath, rand());
// Error check the end of temp file name for ending double slash
if (tempFileName[bufsize] == '\\')
tempFileName[bufsize] = '\0';
// 3. Create temp file
printf("Creating temp file %s\nto store %s\n", tempFileName, srcPath.c_str());
tempFile = fopen(tempFileName, "wb"); // Open the file for writing
if (!tempFile)
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not create temp file! Error %d\n", errorNum);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
printf("Done!\n\n");
printf("------------------- Read the response -------------------\n");
unsigned long n = 0;
unsigned long sum = 0;
printf("Copying %s\n to %s\n", srcPath.c_str(), tempFileName);
// WHERE THE MAGIC HAPPENS - AND WHERE EVERYTHING FAILS!
while ( InternetReadFile(hRequest, lpszDataBuffer, dwSize, &dwRead) && !(bAllDone) )
if (dwRead != 0)
sum = 0;
fwrite(lpszDataBuffer, 1, dwRead, tempFile);
for (unsigned long i = 0; i < dwRead; ++i)
sum += lpszDataBuffer[i];
sum %= 0xFFFF;
printf("Received 4KB block %d. Sum %04X\r", n++, sum);
else
bAllDone = TRUE;
printf("\n");
break;
printf("\n\n------------------- Request Complete ----------------\n");
fclose(tempFile); // Done writing to file
tempFile = fopen(tempFileName, "rb"); // Reopen for reading
//Create the local file
printf("Creating local file %s\n", destPath);
localFile = fopen(destPath, "wb");
if (!localFile)
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not create local file! Windows Error %d\n", errorNum);
fclose(tempFile);
remove(tempFileName); // delete temporary file from machine
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
printf("Done!\n\n");
// Copy the contents from the temp file to the local file
printf("Copying temp file %s contents\nto local file %s\n", tempFileName, destPath);
if (!copyFile(tempFile, localFile))
DWORD errorNum = GetLastError();
fprintf(stderr, "Could not copy temp file to local directory! Windows Error\n", errorNum);
fclose(tempFile);
remove(tempFileName); // delete temporary file from machine
fclose(localFile);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
return false;
printf("Done!\n\n");
// end of logic housekeeping
fclose(tempFile);
printf("Deleting temp file %s\n", tempFileName);
remove(tempFileName); // delete temporary file from machine
printf("Done!\n\n");
fclose(localFile);
printf("Ending Internet Session\n");
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInstance);
printf("Done!\n");
printf("Press Enter to continue\n");
std::cin.get();
return true;
【问题讨论】:
能否请您加载完整的代码,以便其他人试用?缺少一些文件,例如 httpfileretrieval.h。如果代码已准备好构建,将更有利于其他开发人员理解并提出他们的 cmets 和建议。谢谢。 也发生在我身上:以看起来愚蠢为代价,我分享了它对我不起作用的原因。如果你在得到所有数据后调用它也不起作用。 【参考方案1】:您的代码对我有用。您确定服务器正在返回非空响应吗?您可以使用 Fiddler2 之类的工具进行检查。这段代码有很多问题,包括这里的缓冲区溢出:lpszDataBuffer[bufsize] = '\0';
。此外,您使用的是异步模式,但您的读取循环中没有任何异步处理。我建议您在此处发布代码以供审核:https://codereview.stackexchange.com/。
最后一点。如果您只是要等待每个操作完成,那么异步执行操作没有任何好处。您可以不使用 INTERNET_FLAG_ASYNC
标志。这将使您的功能更加简单。
【讨论】:
感谢您回答彼得。是的,你对'INTERNET_FLAG_ASYNC'标志绝对是正确的。我最初让它在控制台上提供交互式输出,让用户查看后台发生的事情,但我决定只按照程序的逻辑顺序输出。当我移除那面旗帜的那一刻,一切都像魅力一样运作。感谢您的帮助!以上是关于InternetReadFile() 似乎没有读取互联网数据的主要内容,如果未能解决你的问题,请参考以下文章
InternetReadFile() 读取数据但返回 false 并将读取的字节数设置为零