Boost logo

Boost Users :

Subject: [Boost-users] boost::asio::async_read_until fills streambuf less than actually received
From: David Demelier (markand_at_[hidden])
Date: 2018-04-02 08:46:21


Hello,

I'm using Asio to read IRC messages asynchronously from a server. I use
boost::asio::async_read_until with "\r\n" as delimiter and a
boost::asio::streambuf as output buffer.

I mostly implemented the code like described on my original
question/answer here:

https://stackoverflow.com/questions/40561097/read-until-a-string-delimi
ter-in-boostasiostreambuf

I sometimes get the bytes_transferred argument bigger that what is
filled into the buffer.

My code looks like this:

    void connection::do_recv(handler_t handler)
    {
        boost::asio::async_read_until(socket_, buffer_, "\r\n", [this,
handler] (auto code, auto xfer) {
            if (code || xfer == 0U)
                handler(std::move(code), message());
            else {
                //assert(buffer_.size() > xfer);
    
                std::cout << "xfer: " << xfer << std::endl;
                std::cout << "size: " << buffer_.size() <<
std::endl;
    
                std::string str(
                    boost::asio::buffers_begin(buffer_.data()),
                    boost::asio::buffers_begin(buffer_.data()) + xfer -
2
                );
    
                buffer_.consume(xfer);
                handler(std::move(code), message::parse(str));
            }
        });
    }
    
    void connection::rflush()
    {
        if (input_.empty())
            return;
    
        do_recv([this] (auto code, auto message) {
            auto h = input_.front();
    
            // Delete first, in case of exceptions.
            input_.pop_front();
    
            if (h)
                h(code, std::move(message));
            if (!code)
                rflush();
        });
    }
    
    void connection::recv(handler_t handler)
    {
        auto in_progress = !input_.empty();
    
        input_.push_back(std::move(handler));
    
        if (!in_progress)
            rflush();
    }

For some reasons, after several calls, I get an assertion failure in
the std::string construction. Because buffer_.size() is actually
smaller than xfer. I could not understand why.

Example of output:

...
...
xfer: 87
size: 141

Note: I've implemented the recv() public function like what I can see
for send in some tutorials. I wanted a queue of handlers so I can
safely call recv() multiple times before first functions finished
completely.

Regards,

-- 
David

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net