Reputation: 483
I'm writing a small boost asio tcp server and client that sends and receives plain text. The communication is more or less request response. During testing I figured I'd just spam the server with data, sending it 100.000 requests.
The message sent from the client to the server:
\n=BEGIN 1,test\n
Hello World: 1
\n=END\n
In the above message the counter goes from 0 to 99.999 (in the above example it is 1 as in "BEGIN 1" and "Hello World: 1").
As stated, this works fine and all 100.000 messages are received by the server, but once all is transferred, the read-handler is invoked up to several times more, although no data is sent from the client.
Reading the data from the streambuf object yields remnants of older messages as in:
IN 61868,test\n
Hello World: 61868
\n=END\n
And:
=END\n
=END\n
The weird thing is that it only seems to happen when the number of messages exceeds a certain amount, but it's not consistent, leading me to believe there is some overflow or UB going on somewhere, and as such I clearly have done something wrong, but I cannot seem to be able to figure out what. The code for reading is:
typedef boost::shared_ptr<boost::asio::streambuf> asio_streambuf_ptr;
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> asio_socket_ptr;
...
void on_read(const asio_socket_ptr& s, const asio_streambuf_ptr& b,
const boost_error_code& e, size_t length) {
if ( !e ) {
std::string temp(boost::asio::buffer_cast<const char*>(b->data()), length);
//process temp
b->consume(length);
} else {
//Handle the error - or close the socket if disconnected
handle_error(s, e);
}
read(s, b);
}
void read(const asio_socket_ptr& s, const asio_streambuf_ptr& buf) {
if (s->is_open()) {
boost::asio::async_read_until(*s, *buf, "\n=END\n",
boost::bind(on_read, s, buf, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
My first implementation of the on_read function used std::istream and std::getline to read each message line by line, but the problem was present there as well, and since the streams are hard to inspect in gdb i rewrote it to make it easier to look into.
Now I must stress that I am new to boost-asio, and that this is my first attempt at making something useful with that part of boost, and as such I do accept that I could well be missunderstanding several of concepts of the asynchronous io system.
So my question: Has anyone experienced this before or have any suggestion to what I'm doing wrong?
I've made an SSCCE, but as it involves a fair amount of code being a server and a client, I think I'll wait to post it here until someone requests it.
Update: The issue seems to be that the client writes messages faster than the server can read them. Throttling the client slightly fixed the issue. Note: Changing the internal buffer sizes did not help, so it seems that the client flooded some os-network buffers or something to that effect.
Upvotes: 3
Views: 1260
Reputation: 2787
You shouldn't continue reading in case of an error -> only when no error is detected. Perhaps you continue reading after the EOF? Move the call to read in the function on read in the if.
Upvotes: 1