WinHTTP télécharge des octets NULL ou est-ce que je copie incorrectement le tampon de résultats?

StackOverflow https://stackoverflow.com/questions/8988000

Question

J'ai récemment porté un programme Wininet entièrement fonctionnant à WinHTTP. Voici une fonction que j'ai écrite pour envelopper une demande de GET entière dans une seule ligne de code:

bool Get(Url url, std::vector<char>& data, ProgressCallbackFunction progressCallback = nullptr) throw()
{
    long cl = -1;
    DWORD clSize = sizeof(cl);
    DWORD readCount = 0;
    DWORD totalReadCount = 0;
    DWORD availableBytes = 0;
    std::vector<char> buf;

    if (_session != NULL)
        throw std::exception("Concurrent sessions are not supported");

    _session = ::WinHttpOpen(_userAgent.c_str(), WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, NULL);
    auto connection = ::WinHttpConnect(_session, url.HostName.c_str(), url.Port, 0);
    auto request = ::WinHttpOpenRequest(connection, TEXT("GET"), url.GetPathAndQuery().c_str(), NULL, NULL, NULL, WINHTTP_FLAG_REFRESH);

    if (request == NULL)
    {
        _lastError = ::GetLastError();
        ::WinHttpCloseHandle(_session);
        _session = NULL;
        return false;
    }

    auto sendRequest = ::WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL);
    if (sendRequest == FALSE)
    {
        _lastError = ::GetLastError();
        ::WinHttpCloseHandle(request);
        ::WinHttpCloseHandle(_session);
        _session = NULL;
        return false;
    }

    if (::WinHttpReceiveResponse(request, NULL))
    {
        if (progressCallback != nullptr && progressCallback != NULL)
        {
            if (!::WinHttpQueryHeaders(request, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, reinterpret_cast<LPVOID>(&cl), &clSize, 0))
            {
                cl = -1;    
            }
        }

        while (::WinHttpQueryDataAvailable(request, &availableBytes))
        {
            if (availableBytes)
            {
                buf.resize(availableBytes + 1);
                auto hasRead = ::WinHttpReadData(request, &buf[0], availableBytes, &readCount);
                totalReadCount += readCount;
                data.insert(data.end(), buf.begin(), buf.begin() + readCount);
                buf.clear();

                if (progressCallback != nullptr && progressCallback != NULL)
                {
                    progressCallback(totalReadCount, cl, getProgress(totalReadCount, cl));
                }
            }
            else
                break;
        }
    }
    else
    {
        _lastError = ::GetLastError();
        ::WinHttpCloseHandle(request);
        ::WinHttpCloseHandle(_session);
        _session = NULL;
        return false;
    }

    ::WinHttpCloseHandle(request);
    ::WinHttpCloseHandle(_session);
    _session = NULL;
    return true;
}

Le code œuvres en ce qu'il télécharge l'URL demandée. Le problème se pose lorsque le serveur ne renvoie pas l'en-tête de longueur de contenu (qui est plus du temps). Le code téléchargera toujours toutes les données, mais il y aura des octets nuls intégrés lorsqu'ils seront convertis en chaîne.

Le code ci-dessus est appelé ceci:

Url url(TEXT("http://msdn.microsoft.com/en-us/site/aa384376"));
Client wc;
std::vector<char> results;
wc.Get(url, results);
StdString html(results.begin(), results.end());
StdOut << html << endl;

StDString est typedef std :: basic_stringu003CTCHAR> Et STDOUT est une macro qui utilise Cout ou WCOUT selon si Unicode est défini.

En raison des nuls intégrés, toute la réponse n'est pas affichée sur la console. La sortie affichée lorsque j'exécute le code avec le débogage peut être visualisé ici (Notez que les ruptures de ligne sont simplement là où le texte est enveloppé dans ma console). Le premier null est vu juste après "__in" à la toute fin et se produit là où la "touche appuyez sur n'importe quelle touche pour continuer ..." La sortie est affichée. Voici un capuchon d'écran de la sortie:

Console output

Voici un capuchon d'écran de visualiseur de texte de la valeur de la variable HTML montrant exactement où les nuls apparaissent par rapport à ce qui est visible:

Text visualizer for html

Est-ce que je fais une mauvaise copie quelque part ou y a-t-il une nuance de winhttp dont je ne sais pas?

Était-ce utile?

La solution

Lors de l'examen plus approfondi de la sortie, ce sont ne pas nuls. Ce sont des caractères Unicode que la console ne peut pas afficher car ils sont stockés de manière incorrecte (et donc converti de manière incorrecte). J'ai pu résoudre le problème dans la méthode GET (et dans le code d'appel) en changeant

std::vector<char>

à

std::vector<unsigned char>

Et maintenant, tout va bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top