正确地异步使用InternetReadFile()的方法

时间:2013-04-01 17:18:25

标签: wininet

我有异步使用WinInet API执行HTTP请求的代码。一般来说,我的代码有效,但我对“正确”的做事方式感到困惑。在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示例代码忽略了InternetReadFile()只读取部分请求缓冲区的可能性?

2 个答案:

答案 0 :(得分:3)

在仔细阅读异步示例之后,我现在看到它重复读取,直到遇到成功读取0字节为止。所以要回答我自己的问题,你必须一遍又一遍地调用InternetReadFile(),并为同步或异步响应做好准备。

答案 1 :(得分:3)

重复读取InternetReadFile()直到它返回TRUE而BytesRead为0是使用InternetReadFile()的正确方法,但如果你异步工作则不够。

正如MSDN所说

  

异步运行时,如果对InternetReadFile的调用未导致已完成的事务,则它将返回FALSE,随后对GetLastError的调用将返回ERROR_IO_PENDING。事务完成后,将使用INTERNET_STATUS_REQUEST_COMPLETE调用先前对InternetSetStatusCallback的调用中指定的InternetStatusCallback。

如果您在异步模式下工作,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仅包含错误代码{ {1}}是dwResult

如果FALSEdwResult,则TRUE包含从Internet读取的数据,Buffer包含异步读取的字节数。

因此,当您异步工作时,最重要的事情之一是BytesReadBuffer 必须在BytesRead次来电之间保持不变,即一定不能在堆栈上分配。否则它有未定义的行为,导致内存损坏等。