2013-04-01 137 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电话之间持久的,即不能在栈上分配。否则它有未定义的行为,导致内存损坏等。

相关问题