Home > Software design >  Why WinApi SendHttpRequest may be slow on VirtualBox machine
Why WinApi SendHttpRequest may be slow on VirtualBox machine

Time:03-06

Testing my app on few machines show that WinApi HttpSendRequest performs slow sometimes. On non virtual machine it takes ~100-~300 ms, same results on virtual machine sending the same request through curl. But sending request with HttpSendRequest on virtual machine with Win10 takes ~5s and on Win7 - ~20s.

Here is a sample code:

...
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;
}

CodePudding user response:

Probably because VirtualBox has a network implementation that's a little bulky(ish). For me, it made a whole new network adapter (Virtual Ethernet, basically). What it does is, the VM thinks it's connected to Ethernet. Then the VirtualBox backend redirects it through my normal Wi-Fi. These kinds of things are very complicated, so it must be just the overhead of translating the virtual Ethernet to Wi-Fi.

(If you are actually using Ethernet physically, replace all my "Wi-Fi" words with "physical Ethernet")

EDIT: curl probably uses a different API for network calling that doesn't use WinAPI, so it could just be a WinAPI problem as well

  • Related