문제

나는 최근에 WinHTTP에 완전히 작동하는 WinInet 프로그램을 이식했습니다. 다음은 전체 코드의 한 줄로 전체 GET 요청을 랩핑하기 위해 작성한 기능입니다.

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

코드 은 요청 된 URL을 다운로드한다는 점에서 작동합니다. 문제는 서버가 콘텐츠 길이 헤더 ( 가장 많이 )를 반환하지 않을 때 발생합니다. 코드는 여전히 모든 데이터를 다운로드하지만 문자열로 변환 될 때 내장 된 null 바이트가 있습니다.

위의 코드는 다음과 같이 호출됩니다.

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은 typedef std :: basic_string 및 stdout은 유니 코드가 정의 된 경우 cout 또는 wcout을 사용하는 매크로입니다.

임베디드 널이므로 모든 응답이 콘솔에 표시되는 것은 아닙니다. 여기에서 볼 수있는 코드를 디버깅하는 코드를 실행할 때 표시되는 출력은 여기에서 볼 수 있습니다 (줄 바꿈은 텍스트가 내 콘솔에 래핑됩니다). 첫 번째 널은 맨 끝에 "__in"직후에 보입니다. "계속할 키를 누르십시오."출력이 표시됩니다. 다음은 출력의 화면 캡입니다.

콘솔 출력

여기에서 널이 보이는 위치와 정확히 나타나는 HTML 변수의 값의 텍스트 시각화 화면 캡입니다.

도움이 되었습니까?

해결책

출력을 추가로 검토하면 nulls가 아닙니다.그들은 잘못 저장되기 때문에 콘솔이 표시 할 수없는 문자를 유니 코드 (따라서 잘못 변환합니다).를 변경하여 Get 메서드 (및 호출 코드)에서 문제를 해결할 수있었습니다.

std::vector<char>
.

~

std::vector<unsigned char>
.

과 지금은 모두 잘됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top