Problems using boost::asio::async_read()

12,773

You're using the local variable buf as the read buffer, which is dangerous and won't work. Also, you're just sending the original contents of that buffer to the handler. So instead, you need to use a buffer with a longer lifetime. Something like this:

class Server
{
.....

boost::array<char, 1> buf;

void Server::accepted()
{
    std::cout << "Accepted!" << std::endl;

    boost::asio::async_read(socket, boost::asio::buffer(buf),
        boost::bind(&Server::handleRead, this, boost::asio::placeholders::error));
}

void Server::handleRead(const boost::system::error_code& error)
{
    if(!error)
    {
        std::cout << "Message: " << buf.data() << std::endl;
    }
    else
    {
        std::cout << "Error occurred." << std::endl;
    }
}

.....
}

edit: or alternatively, using a heap allocated buffer (not sure if the code is right, but you'll get the idea):

void Server::accepted()
{
    std::cout << "Accepted!" << std::endl;

    boost::shared_ptr<boost::array<char, 1>> buf(new boost::array<char, 1>);

    boost::asio::async_read(socket, boost::asio::buffer(*buf),
        boost::bind(&Server::handleRead, this, buf, boost::asio::placeholders::error));
}

void Server::handleRead(boost::shared_ptr<boost::array<char, 1>> buf, const boost::system::error_code& error)
{
    if(!error)
    {
        std::cout << "Message: " << buf->data() << std::endl;
    }
    else
    {
        std::cout << "Error occurred." << std::endl;
    }
}
Share:
12,773

Related videos on Youtube

Zippo
Author by

Zippo

Updated on June 04, 2022

Comments

  • Zippo
    Zippo almost 2 years

    Here's the code I use:

    class Server
    {
    .....
    
    void Server::accepted()
    {
        std::cout << "Accepted!" << std::endl;
    
        boost::array<char, 1> buf;
        boost::asio::async_read(socket, boost::asio::buffer(buf),
            boost::bind(&Server::handleRead, this, buf, boost::asio::placeholders::error));
    }
    
    void Server::handleRead(boost::array<char, 1> buf, const boost::system::error_code& error)
    {
        if(!error)
        {
            std::cout << "Message: " << buf.data() << std::endl;
        }
        else
        {
            std::cout << "Error occurred." << std::endl;
        }
    }
    
    .....
    }
    

    The problem is that I always get the same data from the client: a specific char. In my client I tried sending other char, but still the server shows the same char.

    And when I try to read more than 1 bytes, I get an error that the buf variable is used before it's initialized.

  • Sam Miller
    Sam Miller over 13 years
    +1 when using asynchronous methods, it is the caller's responsibility to ensure the buffer is valid throughout the lifetime of the call.
  • Zippo
    Zippo over 13 years
    Thanks it works, but with a little problem. I configured the client to send "aaaaaa" and the server to read 6 characters. The server is successfully reading the characters but not cleanly: "Message: aaaaaaÌÌÌÌÌÌ(c².ˆ÷0". This is the output I see in the server's console. I've also tried to write buf.data() into a file, but still the same output.
  • Timo
    Timo over 13 years
    That is because the string isn't null terminated. So you need to use a 7 character buffer, and either have the client send a null terminated string or have the server set the 7th character to null manually. Or you could use std::string as the buffer, just remember to call .resize(6) before you use it.
  • Zippo
    Zippo over 13 years
    So the last problem wasn't related to boost::asio :) thanks, it works great.

Related