我正在尝试编写一个异步Wininet应用程序。如果是INTERNET_STATUS_REQUEST_COMPLETE,我会在回调函数中读取数据,并且也会处理ERROR_IO_PENDING错误。但是从互联网读取一些数据后,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;


谁能帮我纠正这个问题?
谢谢大家的帮助...

最佳答案

仅当GetLastError()(或其他任何API)实际上因错误而失败时,InternetReadFileEx()才有意义。否则,您将处理来自早期API调用的错误,给您的代码一种错觉,使您误以为错误可能确实没有发生。您必须注意API返回值,但是您当前忽略了InternetReadFileEx()的返回值。

但是,更糟糕的是,您在异步模式下使用InternetReadFileEx(),但使用的是INTERNET_STATUS_REQUEST_COMPLETE回调处理程序本地的接收缓冲区。如果InternetReadFileEx()失败,并显示ERROR_IO_PENDING错误,则在后台执行读取,并且在读取完成后将触发INTERNET_STATUS_REQUEST_COMPLETE。但是,发生该错误时,您正在中断循环(即使读取仍在进行中),并且该缓冲区将在读取完成之前超出范围。虽然读取仍在进行中,但是接收缓冲区仍在堆栈上,并且InternetReadFileEx()仍在对其进行写入,但是由于您的代码继续执行其他操作,并且可能同时将其重新用于其他用途,并且没有等待读取完成。

您需要重新考虑您的方法。要么:


删除IRF_ASYNC标志,因为这是其余回调代码期望InternetReadFileEx()表现的方式。
重新编写代码以正确地在异步模式下运行。动态分配接收缓冲区(或至少将其存储在异步读取过程中仍保留在范围内的其他位置),除非真正有数据要写入(除非IStream::Write()立即返回TRUE,否则,否则),请不要调用InternetReadFileEx()从先前的INTERNET_STATUS_REQUEST_COMPLETE / InternetReadFileEx()调用中获取具有成功代码的ERROR_IO_PENDING事件),等等。


有许多在线示例和教程,展示了如何在异步模式下使用InternetReadFileEx()。四处搜寻。

关于c - InternetReadFileEx出现10035和1008错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17215489/

10-10 21:20