5

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.

Zippo
  • 15,850
  • 10
  • 60
  • 58

1 Answers1

13

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;
    }
}
Timo
  • 5,125
  • 3
  • 23
  • 29
  • 2
    +1 when using asynchronous methods, it is the caller's responsibility to ensure the buffer is valid throughout the lifetime of the call. – Sam Miller Dec 24 '10 at 17:42
  • 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. – Zippo Dec 24 '10 at 18:01
  • 2
    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. – Timo Dec 24 '10 at 18:29
  • So the last problem wasn't related to boost::asio :) thanks, it works great. – Zippo Dec 24 '10 at 18:38