Поделиться через


Практическое руководство. Работа с асинхронными потоками (C++ REST SDK)

C++ REST SDK (кодовое название "Casablanca") предоставляет потоковые возможности, позволяющие без труда работать с сокетами TCP, файлами на диске и памятью. Потоки C++ REST SDK схожи с потоками, предоставляемыми стандартной библиотекой C++, за исключением того, что в версиях C++ REST SDK используется асинхронность. Для операций ввода-вывода, которые являются потенциально блокирующими, библиотека возвращает pplx::task, а не значение напрямую. На этой странице приведено два примера. В первом показана запись в поток и чтение из потока с помощью контейнеров STL и неразмеченной памяти. Во втором примере создается запрос HTTP GET и часть потока ответа выводится на консоль.

Предупреждение

В этом разделе содержатся сведения о C++ REST SDK 1.0 (кодовое название "Casablanca").Если используется более поздняя версия с веб-страницы Casablanca Codeplex, воспользуйтесь локальной документацией по адресу http://casablanca.codeplex.com/documentation.

Более полный пример, демонстрирующий инструкции #include и using, приводится после этих примеров.

Использование потоков вместе с контейнерами STL и неразмеченной памятью.

В этом примере показана запись в поток и чтение из потока с помощью контейнеров STL и неразмеченной памяти.

// Shows how to read from and write to a stream with an STL container or raw pointer. 
void ReadWriteStream(istream inStream, ostream outStream)
{
    // Write a string to the stream.
    std::string strData("test string to write\n");
    container_buffer<std::string> outStringBuffer(std::move(strData));
    outStream.write(outStringBuffer, outStringBuffer.collection().size()).then([](size_t bytesWritten)
    {
        // Perform actions here once the string has been written...
    });

    // Read a line from the stream into a string.
    container_buffer<std::string> inStringBuffer;
    inStream.read_line(inStringBuffer).then([inStringBuffer](size_t bytesRead)
    {
        const std::string &line = inStringBuffer.collection();

        // Perform actions here after reading line into a string...
    });

    // Write data from a raw chunk of contiguous memory to the stream. 
    // The raw data must stay alive until write operation has finished. 
    // In this case we will place on the heap to avoid any issues. 
    const size_t rawDataSize = 8;
    unsigned char* rawData = new unsigned char[rawDataSize];
    memcpy(&rawData[0], "raw data", rawDataSize);
    rawptr_buffer<unsigned char> rawOutBuffer(rawData, rawDataSize, std::ios::in);
    outStream.write(rawOutBuffer, rawDataSize).then([rawData](size_t bytesWritten)
    {
        delete []rawData;

        // Perform actions here once the string as been written...
    });
}

Доступ к потоку ответа HTTP

Далее показано использование метода web::http::http_response::body для получения объекта concurrency::streams::istream, из которого можно прочесть данные. Для простоты в этом примере на консоль выводятся только первые несколько символов ответа. Сведения о базовой версии, которая извлекает ответ сервера, но не работает с потоком ответа, см. в разделе Практическое руководство. Подключение к серверам HTTP.

// Creates an HTTP request and prints part of its response stream.
pplx::task<void> HTTPStreamingAsync()
{
    http_client client(L"https://www.fourthcoffee.com");

    return client.request(methods::GET).then([](http_response response)
    {
        if(response.status_code() != status_codes::OK)
        {
            // Handle error cases... 
            return pplx::task_from_result();
        }

        // Perform actions here reading from the response stream... 
        // In this example, we print the first 15 characters of the response to the console.
        istream bodyStream = response.body();
        container_buffer<std::string> inStringBuffer;
        return bodyStream.read(inStringBuffer, 15).then([inStringBuffer](size_t bytesRead)
        {
            const std::string &text = inStringBuffer.collection();

            // For demonstration, convert the response text to a wide-character string.
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf16conv;
            std::wostringstream ss;
            ss << utf16conv.from_bytes(text.c_str()) << std::endl;
            std::wcout << ss.str();
        });
    });

    /* Output:
    <!DOCTYPE html>
    */
}

Полный пример

Ниже приведен полный пример.

#include <codecvt>
#include <containerstream.h>
#include <http_client.h>
#include <iostream>
#include <producerconsumerstream.h>
#include <rawptrstream.h>

using namespace concurrency;
using namespace concurrency::streams;
using namespace web::http;
using namespace web::http::client;

// Shows how to read from and write to a stream with an STL container or raw pointer. 
void ReadWriteStream(istream inStream, ostream outStream)
{
    // Write a string to the stream.
    std::string strData("test string to write\n");
    container_buffer<std::string> outStringBuffer(std::move(strData));
    outStream.write(outStringBuffer, outStringBuffer.collection().size()).then([](size_t bytesWritten)
    {
        // Perform actions here once the string has been written...
    });

    // Read a line from the stream into a string.
    container_buffer<std::string> inStringBuffer;
    inStream.read_line(inStringBuffer).then([inStringBuffer](size_t bytesRead)
    {
        const std::string &line = inStringBuffer.collection();

        // Perform actions here after reading line into a string...
    });

    // Write data from a raw chunk of contiguous memory to the stream. 
    // The raw data must stay alive until write operation has finished. 
    // In this case we will place on the heap to avoid any issues. 
    const size_t rawDataSize = 8;
    unsigned char* rawData = new unsigned char[rawDataSize];
    memcpy(&rawData[0], "raw data", rawDataSize);
    rawptr_buffer<unsigned char> rawOutBuffer(rawData, rawDataSize, std::ios::in);
    outStream.write(rawOutBuffer, rawDataSize).then([rawData](size_t bytesWritten)
    {
        delete []rawData;

        // Perform actions here once the string as been written...
    });
}

// Creates an HTTP request and prints part of its response stream.
pplx::task<void> HTTPStreamingAsync()
{
    http_client client(L"https://www.fourthcoffee.com");

    return client.request(methods::GET).then([](http_response response)
    {
        if(response.status_code() != status_codes::OK)
        {
            // Handle error cases... 
            return pplx::task_from_result();
        }

        // Perform actions here reading from the response stream... 
        // In this example, we print the first 15 characters of the response to the console.
        istream bodyStream = response.body();
        container_buffer<std::string> inStringBuffer;
        return bodyStream.read(inStringBuffer, 15).then([inStringBuffer](size_t bytesRead)
        {
            const std::string &text = inStringBuffer.collection();

            // For demonstration, convert the response text to a wide-character string.
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf16conv;
            std::wostringstream ss;
            ss << utf16conv.from_bytes(text.c_str()) << std::endl;
            std::wcout << ss.str();
        });
    });

    /* Output:
    <!DOCTYPE html>
    */
}

int wmain()
{
    // This example uses the task::wait method to ensure that async operations complete before the app exits.  
    // In most apps, you typically don�t wait for async operations to complete.

    streams::producer_consumer_buffer<uint8_t> buffer;
    //ReadWriteStream(buffer.create_istream(), buffer.create_ostream());

    HTTPStreamingAsync().wait();
}

См. также

Другие ресурсы

C++ REST SDK (Codename "Casablanca")