リクエストのコールバック プロシージャで 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;
}
}
}
ここで buffer は、リクエストが開始されたときに 8K を予約したベクターです。前もって感謝します。
OnResponseComplete、OnResponsEerror では、最終的に次のようにも呼び出します。
::WinHttpSetStatusCallback(handle, NULL, 0, 0);
assert(::WinHttpCloseHandle(this->handle));
this->handle = nullptr;