[Boost-users] Boost::Asio read_until and streambuf usage

1,428 views
Skip to first unread message

Gonzalo Garramuno

unread,
Nov 21, 2012, 12:11:35 PM11/21/12
to boost...@lists.boost.org
I have a server that sends three lines, each of which have to be parsed
independently.
I am using read_until but have a problem with its usage. When
read_until reads once, the streambuf seems to contain the three lines
but not in the istream and only when I call read_until several times, I
get the lines.
I am wondering how can I safely read_until the buffer is empty (the 3 or
more lines are read) and then exit the loop.

boost::asio::streambuf buf;

while( 1 )

{
size_t reply_length = boost::asio::read_until( socket_,
buf, '\n' );

std::istream is(&buf);
std::string reply;
std::getline(is, reply); // only 1 line obtained

}

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Igor R

unread,
Nov 21, 2012, 12:56:20 PM11/21/12
to boost...@lists.boost.org
> I have a server that sends three lines, each of which have to be parsed
> independently.
> I am using read_until but have a problem with its usage. When read_until
> reads once, the streambuf seems to contain the three lines but not in the
> istream and only when I call read_until several times, I get the lines.
> I am wondering how can I safely read_until the buffer is empty (the 3 or
> more lines are read) and then exit the loop.
>
> boost::asio::streambuf buf;
>
> while( 1 )
>
> {
> size_t reply_length = boost::asio::read_until( socket_,
> buf, '\n' );
>
> std::istream is(&buf);
> std::string reply;
> std::getline(is, reply); // only 1 line obtained
>
> }


Do you expect std::getline to give you more than 1 line?

Gonzalo Garramuno

unread,
Nov 22, 2012, 1:38:51 PM11/22/12
to boost...@lists.boost.org
On 21/11/12 14:56, Igor R wrote:
> Do you expect std::getline to give you more than 1 line?
No, sorry I was not clear. I expect the streambuf or read_until to have
some way of telling me there's more lines to read. With that piece of
code, the streambuf swallows multiple lines, but getline only gets to
the first line. Only when read_until is run again, the other lines
appear. I need to poll? the socket for more data, but not sure how that
is done in asio.

Igor R

unread,
Nov 22, 2012, 2:06:26 PM11/22/12
to boost...@lists.boost.org
>> Do you expect std::getline to give you more than 1 line?
>
> No, sorry I was not clear. I expect the streambuf or read_until to have
> some way of telling me there's more lines to read. With that piece of code,
> the streambuf swallows multiple lines, but getline only gets to the first
> line. Only when read_until is run again, the other lines appear. I need to
> poll? the socket for more data, but not sure how that is done in asio.

The point is that read_until() may read *more* data than you asked,
but std::getline() always extracts chars until it encounters eol or
until error occurs. So you can iterate over getline() until error in
the istream state -- the last extracted string would be incomplete, so
it should be appended by the next result of read_until.
Alternatively, you can scan the streambuf contents manually, find
eol's and split the whole input as you wish.

Leo Cacciari

unread,
Dec 6, 2012, 9:27:54 AM12/6/12
to boost...@lists.boost.org
Il 22/11/2012 19:38, Gonzalo Garramuno ha scritto:
> On 21/11/12 14:56, Igor R wrote:
>> Do you expect std::getline to give you more than 1 line?
> No, sorry I was not clear. I expect the streambuf or read_until to have
> some way of telling me there's more lines to read. With that piece of
> code, the streambuf swallows multiple lines, but getline only gets to
> the first line. Only when read_until is run again, the other lines
> appear. I need to poll? the socket for more data, but not sure how that
> is done in asio.

This is not the way read_until works. The problem is that it can have
read more data thant what is until the "\n", but it only committed
reply_length bytes. Thus you should do something like the following

typedef boost::asio::streambuf::const_buffers_type buffer_type;
typedef boost::asio::buffers_iterator<buffer_type> iterator;

boost::asio::streambuf buf;

while( 1 ) {
boost::system::error_code ec;

size_t reply_length = boost::asio::read_until( socket_,
buf, '\n',ec);
if (ec) {
// probably connection closed, do something smart
// about it
}
std::string line;
buffer_type input buf.data();

std::copy(iterator::begin(input),iterator::end(input),
std::back_inserter(line));
buf.consume(reply_length);
}



--
Leo Cacciari
Aliae nationes servitutem pati possunt populi romani est propria libertas
Reply all
Reply to author
Forward
0 new messages