2013-04-01 264 views
3

我有代碼使用WinInet API異步執行HTTP請求。一般來說,我的代碼可行,但我對「正確」做事的方式感到困惑。在InternetReadFile()的文件,它規定:異步使用InternetReadFile()的正確方法

,以確保所有數據被檢索,應用程序必須繼續調用 的功能的InternetReadFile,直到該函數返回TRUE和 lpdwNumberOfBytesRead參數等於零。

但在異步模式下,它可能(或可能不會)返回false,並ERROR_IO_PENDING一個錯誤,表示它會異步地做工作,並在完成時調用我的回調。如果我從字面上閱讀文檔,似乎異步調用也可能只是部分讀取所請求的緩衝區,並要求調用方繼續調用InternetReadFile,直到遇到讀取0字節爲止。

使用InternetReadFile()同步看起來像一個典型的實現:

while(InternetReadFile(Request, Buffer, BufferSize, &BytesRead) && BytesRead != 0) 
{ 
    // do something with Buffer 
} 

但是,任何一個呼叫InternetReadFile()可能表明,它會做的工作異步(也許閱讀的一部分,但可能性不是你所有的要求),它變得更加複雜。如果我轉向MSDN sample code作爲指導,實現很簡單,只需簡單地調用InternetReadFile()一次,並期望單個返回即時或異步地讀取整個請求的緩衝區。這是使用此功能的正確方法,還是MSDN示例代碼忽略了只能讀取所請求的緩衝區的一部分的可能性?

回答

3

在仔細閱讀異步示例之後,我現在看到它正在重複讀取,直到遇到成功讀取0字節爲止。因此,要回答我自己的問題,您必須反覆調用InternetReadFile(),併爲同步響應或異步響應做好準備。

3

重複讀取InternetReadFile()直到它返回TRUE並且BytesRead爲0是使用InternetReadFile()的正確方法,但是如果您異步工作則不夠。

由於MSDN說

當以異步方式運行,如果一個的InternetReadFile調用不會在完成交易結果,它將返回FALSE並GetLastError函數的後續調用將返回ERROR_IO_PENDING。當事務完成時,先前調用InternetSetStatusCallback中指定的InternetStatusCallback將與INTERNET_STATUS_REQUEST_COMPLETE一起調用。

所以InternetReadFile()可能返回FALSE,如果你工作在異步方式的最後一個錯誤設置爲ERROR_IO_PENDING值。

InternetSetStatusCallback時將與INTERNET_STATUS_REQUEST_COMPLETE再次調用時,lpvStatusInformation參數將包含INTERNET_ASYNC_RESULT結構的地址(參見InternetStatusCallback callback function)。 INTERNET_ASYNC_RESULT.dwResult成員將包含異步操作的結果(TRUEFALSE,因爲您調用InternetReadFile),並且INTERNET_ASYNC_RESULT.dwError僅在dwResultFALSE時才包含錯誤代碼。

如果dwResultTRUE那麼您的Buffer包含從Internet讀取的數據,並且BytesRead包含異步讀取的字節數。

所以,當你異步工作最重要的事情之一,BufferBytesRead必須InternetStatusCallback電話之間持久的,即不能在棧上分配。否則它有未定義的行爲,導致內存損壞等。

相關問題