tags:

views:

295

answers:

2

I'm using the Boost ASIO library to write a TCP client program.

The protocol starts with a banner line when you connect followed by '\r\n' I can send commands at any time much like smtp.

However, the server can also send me data when I don't ask for it and it's terminated with a '\r\n'

I have a line like to this to read and parse the initial connection banner Which means, stop reading when I get "\r\n".

boost::asio::streambuf response_;
...
boost::asio::async_read_until(socket_, response_, "\r\n",
            boost::bind(&PumpServerClient::HandleReadBanner, this,
                boost::asio::placeholders::error));

But at various times I want to be able to ask the question, is there data available? if there is, read it until "\r\n". I feel like I need a peek function but I can't see where that is.

Ok, perhaps I can call async_read_until again. But consider this... it never ends. The keep reading debug appears once. Obvious, it's waiting forever to complete but never does.

void client::HandleReadRequest(const boost::system::error_code& err)
{
    if (!err){
        // Got some data, print it out
        std::ostringstream ss;
        ss << &response_;

        std::cout << ss.str() << std::endl;

         // Keep reading...
        boost::asio::async_read_until(socket_, response_, "\r\n",
          boost::bind(&client::HandleReadRequest, this, boost::asio::placeholders::error));

        std::cout << "keep reading" << std::endl;
    }
    else
    {
        std::cout << "Error: " << err.message() << "\n";
    }
}

Ok, I think I get it now. I wasn't looking at a full enough example to base my code off.

It looks like calling:

boost::asio::async_read_until(socket_, response_, "\r\n", boost::bind(&client::HandleReadRequest, this, boost::asio::placeholders::error)); means that when a \r\n appears in the response_ buffer, the function HandleReadRequest will be called. I only need to call async_read_until once. unless a write request is called then I need to do a read again... it appears... well I have it working now at least.

A: 

From glancing at the documentation, I'll go with socket_base::bytes_readable, as in:

boost::asio::ip::tcp::socket socket(io_service); 
...
boost::asio::socket_base::bytes_readable command(true);
socket.io_control(command);
std::size_t bytes_readable = command.get();
MSN
+1  A: 

Typically when using async operations in asio, there's no need for a "peek". When data is available, asio will tell you so by calling the handler function you provided. If your handler has not been called, there's no data available.

If you do "peek" at the socket, I suspect that it won't work as you expect because data will be read by asio and passed to the read handler as soon as it's available, it will only be "ready to read" for a tiny interval while the handler is being called. Though it might work as long as no async_read has been started on the socket.

In the case of your async_read_until, you probably just want to post another read request when your read handler is called.

Tim Sylvester
I thought this was the correct answer but it goes forever.
Matt H
Tim Sylvester
See the sample code above. HandleReadRequest calls another HandleReadRequest. More data is sent to it but still, nothing appears
Matt H
Yeah, totally missed that somehow. >_<
Tim Sylvester