简体   繁体   中英

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

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


}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM