Discussion:
[asio-users] Buffer reading only 256 chars or so
Gonzalo Garramuno
2014-02-26 19:28:07 UTC
Permalink
I am using asio asynchronically. I have:

void tcp_session::start_read()
{
// Set a deadline for the read operation.

// input_deadline_.expires_from_now(boost::posix_time::seconds(30));
// input_deadline_.expires_at(boost::posix_time::pos_infin);

// Start an asynchronous operation to read a newline-delimited message.
boost::asio::async_read_until(socket(), input_buffer_, '\n',
boost::bind(&tcp_session::handle_read,
shared_from_this(),
boost::asio::placeholders::error));
}

void tcp_session::handle_read(const boost::system::error_code& ec)
{
if (stopped())
return;

if (!ec)
{
// Extract the newline-delimited message from the buffer.
std::string msg;
std::istream is(&input_buffer_);
is.exceptions( std::ifstream::eofbit );

try {
while ( std::getline(is, msg) )
{
// parse msg
}
}
catch ( std::ios_base::failure& e )
{
}

}

My problem is that when the data sent is too long ( > 256 chars ) I end
up reading only 256 chars or so and my parsing fails. I am obviously
doing something wrong but I do not know how to fix it.
Alejandro Santos
2014-02-26 20:08:51 UTC
Permalink
TCP offers no warranties about the data fragmentation. If for example
you send 100 bytes, on the other end you might receive several chunks
of different sizes, perhaps 100 bytes each chunk.

You should add some buffering logic to your program to reassemble each
received chunk. This is how TCP works.
Post by Gonzalo Garramuno
void tcp_session::start_read()
{
// Set a deadline for the read operation.
// input_deadline_.expires_from_now(boost::posix_time::seconds(30));
// input_deadline_.expires_at(boost::posix_time::pos_infin);
// Start an asynchronous operation to read a newline-delimited message.
boost::asio::async_read_until(socket(), input_buffer_, '\n',
boost::bind(&tcp_session::handle_read,
shared_from_this(),
boost::asio::placeholders::error));
}
void tcp_session::handle_read(const boost::system::error_code& ec)
{
if (stopped())
return;
if (!ec)
{
// Extract the newline-delimited message from the buffer.
std::string msg;
std::istream is(&input_buffer_);
is.exceptions( std::ifstream::eofbit );
try {
while ( std::getline(is, msg) )
{
// parse msg
}
}
catch ( std::ios_base::failure& e )
{
}
}
My problem is that when the data sent is too long ( > 256 chars ) I end
up reading only 256 chars or so and my parsing fails. I am obviously
doing something wrong but I do not know how to fix it.
------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool.
Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer
Customize your own dashboards, set traffic alerts and generate reports.
Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk
_______________________________________________
asio-users mailing list
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
--
Alejandro Santos
Gonzalo Garramuno
2014-02-26 21:29:31 UTC
Permalink
Post by Alejandro Santos
TCP offers no warranties about the data fragmentation. If for example
you send 100 bytes, on the other end you might receive several chunks
of different sizes, perhaps 100 bytes each chunk.
You should add some buffering logic to your program to reassemble each
received chunk. This is how TCP works.
I believe input_buffer_ ( which is of type boost::streambuf ) should
handle the joining of different segments together. Or maybe I read the
docs wrong.
David Schwartz
2014-02-26 22:48:58 UTC
Permalink
Post by Gonzalo Garramuno
My problem is that when the data sent is too long ( > 256 chars ) I end
up reading only 256 chars or so and my parsing fails. I am obviously
doing something wrong but I do not know how to fix it.
You're not doing anything wrong. This is expected behavior. If the parsing
fails because you haven't read all the data, go and read some more until
your parsing succeeds. That's how you implement a protocol on top of a
byte-stream protocol like TCP.

DS
Roger Austin (Australia)
2014-02-26 23:38:04 UTC
Permalink
I don't think that's right. According to the documentation of async_read_until
The asynchronous operation will continue until one of the following conditions is true:

* The get area of the streambuf contains the specified delimiter.
* An error occurred.
I suspect the problem is that (as the docs state) the buffer may contain characters after the delimiter (i.e. part of the next line). You should not consume these characters in your handler. So you need to change:


while ( std::getline(is, msg) )

{

// parse msg

}

to


if ( std::getline(is, msg) )

{

// parse msg

}

From: David Schwartz [mailto:***@gmail.com]
Sent: Thursday, 27 February 2014 9:49 AM
To: asio-***@lists.sourceforge.net
Subject: Re: [asio-users] Buffer reading only 256 chars or so


On Wed, Feb 26, 2014 at 11:28 AM, Gonzalo Garramuno <***@gmail.com<mailto:***@gmail.com>> wrote:

My problem is that when the data sent is too long ( > 256 chars ) I end
up reading only 256 chars or so and my parsing fails. I am obviously
doing something wrong but I do not know how to fix it.


You're not doing anything wrong. This is expected behavior. If the parsing fails because you haven't read all the data, go and read some more until your parsing succeeds. That's how you implement a protocol on top of a byte-stream protocol like TCP.
DS
Gonzalo Garramuno
2014-02-27 14:14:07 UTC
Permalink
I don’t think that’s right. According to the documentation of
async_read_until
* The get area of the streambuf contains the specified delimiter.
* An error occurred.
I suspect the problem is that (as the docs state) the buffer may
contain characters after the delimiter (i.e. part of the next line).
You should not consume these characters in your handler. So you need
while ( std::getline(is, msg) )
{
// parse msg
}
to
if ( std::getline(is, msg) )
{
// parse msg
}
Thank you very much!!! That did the trick!

Loading...