[asio] buffered_read_stream issue, with async_read()

Hi, I am using boost asio in a project. My program has a TCP protocol which reads a fixed size message header, followed by a variable-sized message body. It is possible to have a message with a 0-byte body, and it is possible that no messages are received for some time. I have an issue when attempting to async_read() a 0-byte body with the buffered_read_stream, detailed here: (1) My program reads a fixed-sized header (2) After this succeeds, my program issues an async read for 0 bytes, for the message body (3) buffered_read_stream sees that storage_ is empty, so it calls async_fill(), to fill it (4) no more messages arrive for some time, so there is no data available to fill (5) BUG -> My program's 0-byte read timer expires, rather than the read() succeeding and calling my handler immediately If I use the boost::asio::tcp::socket instead of the buffered_read_stream, the 0-byte read occurs immediately, and does not time out. I believe the read() with the buffered_read_stream is getting 'blocked' in async_fill(), rather than succeeding immediately. Do you think the buffered_read_stream should have special cases for 0 byte reads to cover this case, or do you think client code should avoid issuing 0 byte reads? Thanks, Brad

brad higgins wrote:
Hi, I am using boost asio in a project. My program has a TCP protocol which reads a fixed size message header, followed by a variable-sized message body. It is possible to have a message with a 0-byte body, and it is possible that no messages are received for some time.
I have an issue when attempting to async_read() a 0-byte body with the buffered_read_stream, detailed here:
(1) My program reads a fixed-sized header (2) After this succeeds, my program issues an async read for 0 bytes, for the message body (3) buffered_read_stream sees that storage_ is empty, so it calls async_fill(), to fill it (4) no more messages arrive for some time, so there is no data available to fill (5) BUG -> My program's 0-byte read timer expires, rather than the read() succeeding and calling my handler immediately
If I use the boost::asio::tcp::socket instead of the buffered_read_stream, the 0-byte read occurs immediately, and does not time out. I believe the read() with the buffered_read_stream is getting 'blocked' in async_fill(), rather than succeeding immediately.
Do you think the buffered_read_stream should have special cases for 0 byte reads to cover this case, or do you think client code should avoid issuing 0 byte reads?
Thanks, Brad _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Brad - Perhaps you can consider changing your completion routine for the header read. If the header indicates that the body is 0 bytes then there is no need to read a body. Simply read the next header. I have a similar setup for some of servers. Best Regards - michael -- ---------------------------------- Michael Caisse Object Modeling Designs www.objectmodelingdesigns.com

Hi Michael,
Perhaps you can consider changing your completion routine for the header read. If the header indicates that the body is 0 bytes then there is no need to read a body. Simply read the next header.
That would certainly fix the issue, and is what I have done in my program. I was raising the issue here, however, to see if people thought this was a bug in the implementation of buffered_read_stream. It is an edge case, which occurs only when attempting a 0-byte read AND when there are no bytes available to be read from the socket. If there is more data to be read, 0-byte reads are handled immediately and successfully. In addition, the behavior is different from issuing 0 byte reads on the tcp::socket directly. Apart from this issue, I was able to wrap the tcp::socket with the buffered_read_stream seamlessly. Do you think I have found a bug, or are 0-byte reads always to be avoided? Thanks, Brad
participants (3)
-
brad higgins
-
Michael Caisse
-
Peter Simons