简体   繁体   中英

Reading from boost asio streambuf keeps bytes in buffer

I have a problem with reading from boost asio's stream. The first invocation of an async_read_until gives me 460 bytes transfered( I checked that with wireshark). After that I use an istream initialized with the streambuf pointer to use std::copy_n with an istreambuf_iterator. That works fine and the target of std::copy_n holds the request up to the delimiter sequence.

The strange thing happens after the next call to async_read_until. It seems that the last character was not read from the streambuf so the next handler call gives me one byte more than the actual size of the request.

Are there any limitations using istream with asio's streambuf?

In addition to the comments, here's a little demo program that shows two ways of interacting with an asio::streambuf .

One way wraps the streambuf in i/o streams, the other uses direct access with prepare/commit and data/consume.

#include <boost/asio.hpp>
#include <iostream>
#include <string>
#include <algorithm>
#include <memory>

namespace asio = boost::asio;

void direct_insert(asio::streambuf& sb, std::string const& data)
{
    auto size = data.size();
    auto buffer = sb.prepare(size);
    std::copy(begin(data), end(data), asio::buffer_cast<char*>(buffer));
    sb.commit(size);
}

void stream_insert(asio::streambuf& sb, std::string const& data)
{
    std::ostream strm(std::addressof(sb));
    strm << data;
}

std::string extract_istream(asio::streambuf& sb)
{
    std::istream is(std::addressof(sb));
    std::string line;
    std::getline(is, line);
    return line;
}

std::string extract_direct(asio::streambuf& sb)
{
    auto buffer = sb.data();
    auto first = asio::buffer_cast<const char*>(buffer);
    auto bufsiz = asio::buffer_size(buffer);
    auto last = first + bufsiz;

    auto nlpos = std::find(first, last, '\n');

    auto result = std::string(first, nlpos);

    auto to_consume = std::min(std::size_t(std::distance(first, nlpos) + 1), bufsiz);
    sb.consume(to_consume);
    return result;
}

int main()
{
    asio::streambuf buf;
    direct_insert(buf, "The cat sat on the mat\n");
    stream_insert(buf, "The cat sat on the mat\n");

    auto s1 = extract_direct(buf);
    auto s2 = extract_istream(buf);

    std::cout << s1 << "\n" << s2 << "\n";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM