Having a hard time understanding a few concepts with Boost ASIO TCP with async_read and async_write

boost, boost-asio, c++, networking, tcp

Solution

Conceptually, `async_read` waits for data to be received. You should call it any time you want something to happen after data is received and a read isn't already pending. Similarly, `async_write` waits for data to be written. You should call it any time you need to write data and a write isn't already pending.

You should call `async_read` when you complete the connection. Before your `async_read` handler returns, it should probably call `async_read` again.

When you need to write to the connection, you should call `async_write` (if a write isn't already pending). In your `async_write` handler, if you still need to write more, you should call `async_write` again.

If no read is already pending, you can call `async_read` in your write handler, if you wish to resume reading after you finish writing. You can also just keep a read always pending. That's up to you.

You should not check if there's anything to read before calling `async_read`. The point of `async_read` is for it to complete when there's something to read. It's a smart way of waiting and doing other things in the meantime.

Problem

I'm having a hard time understand the correct way I should structure a tcp client when using async_read and async_write. The examples seem to do a async_read after connecting and then have async_write in the handler. In the case of my client and sever, when the client connects it needs to check a queue of messages to write and check to see if anything needs to be read. One of the things I'm having a hard time with is understanding how this would work asynchronously. What I envision is in the async_connect handler, the thread would call async_write if anything is in the sendQueue and call async_read over and over. Or should it check if anything is available to be read before it does an async_read? Below is an example of what I'm talking about. ``` void BoostTCPConnection::connectHandler() { setRunning(true); while (isRunning()) { //If send Queue has messages if ( sendSize > 0) { //Calls to async_write send(); } boost::shared_ptr<std::vector<char> > sizeBuffer(new std::vector<char>(4)); boost::asio::async_read(socket_, boost::asio::buffer(data, size), boost::bind(&BoostTCPConnection::handleReceive, shared_from_this(), boost::asio::placeholders::error, sizeBuffer)); } } void BoostTCPConnection::handleReceive(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > sizeBuffer) { if (error) { //Handle Error return; } size_t messageSize(0); memcpy((void*)(&messageSize),(void*)sizeBuffer.data(),4); boost::shared_ptr<std::vector<char> > message(new std::vector<char>(messageSize) ); //Will this create a race condition with other reads? //Should a regular read happen here boost::asio::async_read(socket_, boost::asio::buffer(data, size), boost::bind(&BoostTCPConnection::handleReceiveMessage, shared_from_this(), boost::asio::placeholders::error, message)); } void BoostTCPConnection::handleReceiveMessage(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > rcvBuffer) { if (error) { //Handle Error return; } boost::shared_ptr<std::string> message(new std::string(rcvBuffer.begin(),rcvBuffer.end())); receivedMsgs_.push_back(message); } void BoostTCPConnection::handleWrite(const boost::system::error_code& error,size_t bytes_transferred) { //Success if (error.value() == 0) return; //else handleError } ```

Original source

Related problems