为什么 WinApi SendHttpRequest 在 VirtualBox 机器上可能会很慢
Why WinApi SendHttpRequest may be slow on VirtualBox machine
在几台机器上测试我的应用程序表明 WinApi HttpSendRequest
有时执行缓慢。在非虚拟机上需要 ~100-~300 毫秒,虚拟机通过 curl
发送相同请求的结果相同。但是在使用 Win10 的虚拟机上使用 HttpSendRequest
发送请求需要大约 5 秒,而在 Win7 上需要大约 20 秒。
这是一个示例代码:
...
auto success = OpenInternet();
if (success) {
success = AssignHandles(request);
}
if (success) {
success = SendHttpRequest(request);
}
...
bool OpenInternet(bool reset)
{
if (openHandle == NULL) {
openHandle = InternetOpen(userAgent.c_str(), openAccessType, proxyConfigString, NULL, 0);
if (openHandle != NULL) {
if (IsWindowsVistaOrGreater()) {
BOOL enable = TRUE;
InternetSetOption(openHandle, INTERNET_OPTION_HTTP_DECODING, &enable, sizeof(enable));
}
}
}
return (openHandle == NULL);
}
bool AssignHandles(Request& request)
{
bool success = AssignConnectHandle(request);
if (success) {
success = AssignRequestHandle(request);
if (!success) {
InternetCloseHandle(request.connectHandle);
}
}
return success;
}
bool AssignConnectHandle(Request& request)
{
request.connectHandle = InternetConnect(
openHandle,
request.host.c_str(),
(request.secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT),
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
INTERNET_NO_CALLBACK);
return (request.connectHandle == NULL);
}
bool AssignRequestHandle(Request& request)
{
LPCWSTR pszAcceptTypes[] = {acceptTypeHeader.c_str(), NULL};
request.requestHandle = HttpOpenRequest(
request.connectHandle,
GetRequestMethod(request.type).c_str(),
request.path.c_str(),
httpVersion.c_str(),
NULL,
pszAcceptTypes,
GetRequestFlags(request.secure),
NULL);
return (request.connectHandle == NULL);
}
bool SendHttpRequest(Request& request)
{
std::wstring headers = PrepareHeaders(request);
bool success = HttpSendRequest(
request.requestHandle,
headers.empty() ? NULL : headers.c_str(),
(uint32_t)headers.size(),
(request.data != NULL) ? (void*)request.data->c_str() : NULL,
(request.data != NULL) ? (uint32_t)request.data->length() : 0)
!= 0;
return success;
}
可能是因为 VirtualBox 的网络实现有点笨重。对我来说,它制作了一个全新的网络适配器(基本上是虚拟以太网)。它所做的是,VM 认为它已连接到以太网。然后 VirtualBox 后端通过我的正常 Wi-Fi 重定向它。这些事情很复杂,所以肯定只是将虚拟以太网翻译成Wi-Fi的开销。
(如果您实际上是在物理上使用以太网,请将我所有的“Wi-Fi”单词替换为“物理以太网”)
编辑: curl
可能使用不同的 API 进行不使用 WinAPI 的网络调用,所以它可能只是也是 WinAPI 问题
在几台机器上测试我的应用程序表明 WinApi HttpSendRequest
有时执行缓慢。在非虚拟机上需要 ~100-~300 毫秒,虚拟机通过 curl
发送相同请求的结果相同。但是在使用 Win10 的虚拟机上使用 HttpSendRequest
发送请求需要大约 5 秒,而在 Win7 上需要大约 20 秒。
这是一个示例代码:
...
auto success = OpenInternet();
if (success) {
success = AssignHandles(request);
}
if (success) {
success = SendHttpRequest(request);
}
...
bool OpenInternet(bool reset)
{
if (openHandle == NULL) {
openHandle = InternetOpen(userAgent.c_str(), openAccessType, proxyConfigString, NULL, 0);
if (openHandle != NULL) {
if (IsWindowsVistaOrGreater()) {
BOOL enable = TRUE;
InternetSetOption(openHandle, INTERNET_OPTION_HTTP_DECODING, &enable, sizeof(enable));
}
}
}
return (openHandle == NULL);
}
bool AssignHandles(Request& request)
{
bool success = AssignConnectHandle(request);
if (success) {
success = AssignRequestHandle(request);
if (!success) {
InternetCloseHandle(request.connectHandle);
}
}
return success;
}
bool AssignConnectHandle(Request& request)
{
request.connectHandle = InternetConnect(
openHandle,
request.host.c_str(),
(request.secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT),
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
INTERNET_NO_CALLBACK);
return (request.connectHandle == NULL);
}
bool AssignRequestHandle(Request& request)
{
LPCWSTR pszAcceptTypes[] = {acceptTypeHeader.c_str(), NULL};
request.requestHandle = HttpOpenRequest(
request.connectHandle,
GetRequestMethod(request.type).c_str(),
request.path.c_str(),
httpVersion.c_str(),
NULL,
pszAcceptTypes,
GetRequestFlags(request.secure),
NULL);
return (request.connectHandle == NULL);
}
bool SendHttpRequest(Request& request)
{
std::wstring headers = PrepareHeaders(request);
bool success = HttpSendRequest(
request.requestHandle,
headers.empty() ? NULL : headers.c_str(),
(uint32_t)headers.size(),
(request.data != NULL) ? (void*)request.data->c_str() : NULL,
(request.data != NULL) ? (uint32_t)request.data->length() : 0)
!= 0;
return success;
}
可能是因为 VirtualBox 的网络实现有点笨重。对我来说,它制作了一个全新的网络适配器(基本上是虚拟以太网)。它所做的是,VM 认为它已连接到以太网。然后 VirtualBox 后端通过我的正常 Wi-Fi 重定向它。这些事情很复杂,所以肯定只是将虚拟以太网翻译成Wi-Fi的开销。
(如果您实际上是在物理上使用以太网,请将我所有的“Wi-Fi”单词替换为“物理以太网”)
编辑: curl
可能使用不同的 API 进行不使用 WinAPI 的网络调用,所以它可能只是也是 WinAPI 问题