我正在尝试编写Asyncronous Wininet应用程序。在INTERNET_STATUS_REQUEST_COMPLETE的情况下,我在回调函数中读取数据,并且我也处理了ERROR_IO_PENDING错误。但是在从Internet读取一些数据之后,InternetReadFileEx函数给了我10035 = WSAEWOULDBLOCK(无法立即完成非阻塞套接字操作)错误。在那个错误之后我再次调用InternetReadFileEx,这次它给了我1008 = ERROR_NO_TOKEN(试图引用一个不存在的令牌。)错误。我认为我的设计不正确,因此我收到了这些错误。
以下是我的代码片段:
case INTERNET_STATUS_REQUEST_COMPLETE:
{
BOOL bAllDone= FALSE;
DWORD lastError;
do
{
//Create INTERNET_BUFFERS
char m_pbReadBuffer[4096];
INTERNET_BUFFERS BuffersIn;
ZeroMemory(&BuffersIn, sizeof(INTERNET_BUFFERS));
BuffersIn.dwStructSize = sizeof(INTERNET_BUFFERS);
BuffersIn.lpvBuffer = m_pbReadBuffer;
BuffersIn.dwBufferLength = 4096;
InternetReadFileEx(ReqContext->File, &BuffersIn, IRF_ASYNC, 1);
//HERE I GOT THOSE 10035 and 1008 ERRORS
lastError = GetLastError();
if(lastError == 997) // handling ERROR_IO_PENDING
break;//break the while loop
//append it to my ISTREAM
(ReqContext->savedStream)->Write(BuffersIn.lpvBuffer, BuffersIn.dwBufferLength, NULL);
if (BuffersIn.dwBufferLength == 0)
bAllDone = TRUE;
}while(bAllDone == FALSE);
//delete[] m_pbReadBuffer;
if(bAllDone == TRUE && lastError== 0)
{
//these are for passing the ISTREAM to the function which calls "InternetOpenUrl"
LARGE_INTEGER loc;
loc.HighPart = 0;
loc.LowPart = 0;
ReqContext->savedStream->Seek(loc, STREAM_SEEK_SET, NULL);
ReqContext->savedCallback->OnUrlDownloaded(S_OK, ReqContext->savedStream); //Tell silverlight ISTREAM is ready
ReqContext->savedStream->Release();
ReqContext->savedCallback->Release();
InternetCloseHandle(ReqContext->File);
InternetSetStatusCallback(ReqContext->Connection, NULL);
InternetCloseHandle(ReqContext->Connection);
delete[] ReqContext;
}
}
break;
任何人都可以帮我纠正一下吗? 谢谢大家的帮助...
答案 0 :(得分:1)
GetLastError()
仅在InternetReadFileEx()
(或其他任何API)实际上因错误而失败时才有意义。否则,您将处理早期API调用中的错误,从而为您的代码提供错误的错觉,即错误发生时可能没有错误。您必须注意API返回值,但您当前忽略了InternetReadFileEx()
的返回值。
然而,更糟糕的是,您在异步模式下使用InternetReadFileEx()
但是您正在使用INTERNET_STATUS_REQUEST_COMPLETE
回调处理程序本地的接收缓冲区。如果InternetReadFileEx()
因ERROR_IO_PENDING
错误而失败,则会在后台执行读取操作,并在读取完成时触发INTERNET_STATUS_REQUEST_COMPLETE
。但是,当发生该错误时,您正在打破循环(即使读取仍在进行中),并且该缓冲区将在读取完成之前超出范围。虽然读取仍在进行中,但接收缓冲区仍在堆栈中,InternetReadFileEx()
仍在写入,但它可能会同时重新用于其他事情,因为您的代码继续执行其他操作事情并没有等待读完。
你需要重新思考你的方法。之一:
删除IRF_ASYNC
标记,因为这是其余回调代码期望InternetReadFileEx()
的行为。
重新编写代码以正确操作异步模式。动态分配接收缓冲区(或者至少将其存储在异步读取期间保留在范围内的其他位置),除非实际上有要写入的数据,否则不要调用IStream::Write()
(仅当InternetReadFileEx()
返回TRUE时才离开,或者您收到来自之前INTERNET_STATUS_REQUEST_COMPLETE
/ InternetReadFileEx()
来电的成功代码的ERROR_IO_PENDING
事件等。
有大量在线示例和教程介绍如何在异步模式下使用InternetReadFileEx()
。搜索。