views:

37

answers:

2

Hi all,

I'm experimenting with Boost::asio, and I'm trying to make a client that reads and outputs to console packets sent from a server. The server uses a proprietary protolcol. It sends a timer update every second, responds to ping, and can reply with a list of files when the client asks for it. I have a decent grasp of asynchronous networking, but I'm having a problem. Here's the code:

class JReader
{
public:
  JReader(boost::asio::io_service &io_s)
    : socket_(io_s)
  {
    tcp::resolver resolver(io_s);
    tcp::resolver::query query("xxxx", "yyyy");
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
    tcp::resolver::iterator end;

    boost::system::error_code error = boost::asio::error::host_not_found;
    while (error && endpoint_iterator != end)
    {
      socket_.close();
      socket_.connect(*endpoint_iterator++, error);
    }
    if (error)
    {     
      throw boost::system::system_error(error);
    }


    boost::asio::async_write(socket_, boost::asio::buffer(connect, 12), boost::bind(&JReader::handle_write, this));
    boost::asio::async_write(socket_, boost::asio::buffer(getlist, 3), boost::bind(&JReader::handle_write, this));

    boost::asio::async_read(socket_, boost::asio::buffer(buf_, BUF_SIZE), boost::bind(&JReader::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
  }
private:

  void handle_read(const boost::system::error_code err, size_t bytes)
  {        
    std::cout<<std::endl<<std::string(buf_, bytes);
    boost::asio::async_read(socket_, boost::asio::buffer(buf_, BUF_SIZE), boost::bind(&JReader::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
  }

  void handle_write()
  {
    //TODO: finish this!
    std::cout<<std::endl<<"Wrote something";

  }

  static const int BUF_SIZE = 256;
  char buf_[BUF_SIZE];
  tcp::socket socket_;
};

The program reads from the server and outputs data to console -- but the motherboard makes a terrible beeping sound. I'm pretty sure it has something to do with my handle_read loop.

What is the correct, nonblocking way of continually listening to a server?

+2  A: 

Ah ha! My use of asio was correct, but my mistake was streaming binary data to std::cout!! I used a filestream instead, and now it works. :)

LogicalUnit
A: 

You aren't using async_write correctly, posting two asynchronous writes concurrently is an application error. This is described in documentation for async_write

This operation is implemented in terms of zero or more calls to the stream's async_write_some function, and is known as a composed operation. The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.

You most likely are observing correct behavior because the data you are sending is so short (12 and 3 bytes, respectively). I suggest posting the second async_write after the handler for your first one is invoked.

Sam Miller