我在请求的回调过程中得到了很多 ERROR_INTERNET_CANNOT_CONNECT (12029 代码)。我在异步模式下(在服务器上)使用 WinHttp。在这种情况下,您如何干净地关闭连接。你只是使用这样的东西(就像你通常关闭连接一样?):
::WinHttpSetStatusCallback(handle, NULL, 0, 0);
::WinHttpCloseHandle(this->handle));
我问这个是因为我有一些奇怪的与 winhttp dll 相关的内存泄漏,发生在所描述的情况下(想要创建数百个可能被公司内部防火墙阻止的并发连接或目标服务器丢弃连接)。我已经在 msdn 上查看了 WinHttpCloseHandle 的文档...
以下是我如何处理回调状态:
template <typename T>
void WinHttp::AsyncRequest<T>::OnCallback(DWORD code, const void* info, DWORD length)
{
T* pT = static_cast<T*>(this);
switch (code)
{
case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
{
HRESULT result = pT->OnWriteData();
if (FAILED(result))
{
throw CommunicationException(::GetLastError());
}
if (S_FALSE == result)
{
if (!::WinHttpReceiveResponse(handle, 0)) // reserved
{
throw CommunicationException(::GetLastError());
}
}
break;
}
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
{
DWORD statusCode;
DWORD statusCodeSize = sizeof(DWORD);
if (!::WinHttpQueryHeaders(handle, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX))
{
throw CommunicationException(::GetLastError());
}
pT->OnStatusCodeReceived(statusCode);
if (!::WinHttpQueryDataAvailable(handle, 0))
{
// If a synchronous error occured, throw error. Otherwise
// the query is successful or asynchronous.
throw CommunicationException(::GetLastError());
}
break;
}
case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
{
unsigned int size = *((LPDWORD) info);
if (size == 0)
{
pT->OnResponseComplete(S_OK);
}
else
{
unsigned int sizeToRead = (size <= chunkSize) ? size : chunkSize;
if (!::WinHttpReadData(handle, &buffer[0], sizeToRead, 0)) // async result
{
throw CommunicationException(::GetLastError());
}
}
break;
}
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
{
if (length != 0)
{
pT->OnReadComplete(&buffer[0], length);
if (!::WinHttpQueryDataAvailable(handle, 0))
{
// If a synchronous error occured, throw error. Otherwise
// the query is successful or asynchronous.
throw CommunicationException(::GetLastError());
}
}
else
{
pT->OnResponseComplete(S_OK);
}
break;
}
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
{
{
throw CommunicationException(::GetLastError());
}
break;
}
}
}
这里的缓冲区是一个向量,一旦发起请求,就保留了 8K。提前致谢。
在 OnResponseComplete, OnResponsEerror 我最终也调用:
::WinHttpSetStatusCallback(handle, NULL, 0, 0);
assert(::WinHttpCloseHandle(this->handle));
this->handle = nullptr;