为什么 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 问题