2013-06-20 59 views
0

我想寫一個Asyncronous Wininet應用程序。我在INTERNET_STATUS_REQUEST_COMPLETE的情況下讀取回調函數中的數據,並處理ERROR_IO_PENDING錯誤。但是在從互聯網上讀取一些數據後,InternetReadFileEx函數給我10035 = WSAEWOULDBLOCK(一個非阻塞套接字操作無法立即完成)的錯誤。之後,我再次調用InternetReadFileEx,這次它給了我1008 = ERROR_NO_TOKEN(試圖引用一個不存在的令牌)錯誤。我認爲我的設計不正確,因此我收到了這些錯誤。InternetReadFileEx給出10035和1008錯誤

這裏是我的代碼片段:

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; 

誰能給我一個手糾正? 謝謝大家的幫助......

回答

1

GetLastError()只有在InternetReadFileEx()(或其他任何API,對於這個問題)實際上失敗並出現錯誤時纔有意義。否則,您將會處理來自早期API調用的錯誤,從而讓您的代碼錯誤地認爲發生錯誤時可能不會發生錯誤。您必須注意API返回值,但是您目前忽略了InternetReadFileEx()的返回值。

儘管如此,您在異步模式下使用的是InternetReadFileEx(),但是您使用的回調處理程序的本地接收緩衝區爲InternetReadFileEx()。如果InternetReadFileEx()ERROR_IO_PENDING錯誤而失敗,則讀取將在後臺執行,並且INTERNET_STATUS_REQUEST_COMPLETE將在讀取完成時觸發。但是,如果發生該錯誤,則會破壞循環(即使讀取仍在進行中),並且在讀取完成之前該緩衝區將超出範圍。雖然讀取仍在進行中,但接收緩衝區仍在堆棧中,並且InternetReadFileEx()仍在寫入,但它可能會同時被其他事物重用,因爲您的代碼移動到做其他事情並且沒有等待閱讀完成。

你需要重新思考你的方法。或者:

  1. 刪除IRF_ASYNC標誌,因爲那是多麼的回調代碼的其餘部分期待InternetReadFileEx()的行爲。

  2. 重新編寫代碼以正確運行異步模式。動態分配接收緩衝區(或至少將其存儲在異步讀取期間保留在其他地方的其他地方),除非您實際上有要寫入的數據(只有當InternetReadFileEx()立即返回TRUE,或者您獲得INTERNET_STATUS_REQUEST_COMPLETE事件時才調用IStream::Write()從早期的InternetReadFileEx()/ERROR_IO_PENDING呼叫的成功代碼)等

有很多網上的例子和教程,說明如何在異步模式下使用InternetReadFileEx()。到處搜索。

+0

謝謝你的建議。我解決了我的問題。 –