Boost.Asio streambufからstd::stringに変換する

streambuf::data()で、mutable_bufferまたはconst_bufferがとれるので、それに対してbuffer_castを使用する。

void receive(boost::asio::streambuf& buffer)
{
    const std::string result = boost::asio::buffer_cast<const char*>(buffer.data());
}

よくある、streambufをstd::istreamを通じてstd::stringに変換するようなサンプルは、ストリームによって必要なスペースが削られたりと、ストリーム固有の問題で嵌ることがあるので、この方法が素直で簡単です。


サンプル

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>

namespace asio = boost::asio;
namespace ip = asio::ip;

struct receiver {
    typedef void result_type;

    void operator()(const boost::system::error_code& error, asio::streambuf& buffer)
    {
        if (error) {
            std::cout << error.message() << std::endl;
        }
        else {
            const std::string str = asio::buffer_cast<const char*>(buffer.data());
            std::cout << str << std::endl;
        }
    }
};

int main()
{
    asio::io_service io_service;

    ip::tcp::socket soc(io_service);
    soc.connect(ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 31400));

    asio::streambuf buffer;
    asio::async_read_until(soc, buffer, '\n',
            boost::bind(receiver(), _1, boost::ref(buffer)));

    io_service.run();
}

さらに、ここで使用しているboost::asio::async_read_until()は、指定したデリミタまでを読み込みむための関数。'\n'などを指定すれば1行分読むことになる。受信するデータの末尾がわかってる場合などに使用する。