0

I am calling my server via TCP/IP. I am sending a couple of chars and want to receive an answer, that is send by my acknowledge-fct. But I only receive as many chars as I sent to the server.


constexpr int maxInputBufferLength{1024};

using boost::asio::ip::tcp;


struct session
   : public std::enable_shared_from_this<session>
{

public: 
    session(tcp::socket socket)
        : socket_(std::move(socket))
    {
    }

    void start(){
        do_read();
    }

private:
    void do_read(){
        auto self(shared_from_this());
        socket_.async_read_some(boost::asio::buffer(data_, maxInputBufferLength),
                [this, self](boost::system::error_code ec, std::size_t length)

        {
            command_t currentCommand{data_};
            if(currentCommand.commandStringVector.front()==driveCommand){
                acknowledge("driveCommand triggered by TCP");
            }
            ....

    }

    void acknowledge(std::string ackmessage){
        auto self(shared_from_this());
        boost::asio::async_write(socket_, boost::asio::buffer(ackmessage, maxInputBufferLength),
                [this, self, ackmessage](boost::system::error_code ec, std::size_t length)
                {
                    std::cout << ackmessage <<"\n";
                    if(ec.value()){
                        std::cerr << ec.category().name() << ':' << ec.value() << "\n";
                    }
                });
    }

    char data_[maxInputBufferLength];

};

According to my little knowledge, my acknowledge function that calls async_write with its own boost::asio::buffer should send the whole buffer, which should contain ackmessage with a length of maxInputBufferLength which is a global constexpr int.

bjoekeldude
  • 338
  • 3
  • 11

1 Answers1

2

You have undefined behaviour, because you pass local variable into buffer. buffer is only wrapper for string, it can be treated as pair: pointer to data and size of data, it doesn't make copy of ackmessage. You need to ensure that ackmessage exists until handler for async_write is called. async_write returns immediately, so what you have now looks like:

acknowledge ()
{
    ackmessage // local variable
    async_write is called, it creates buffer to askmessage, pointer to string is stored
    // async_write returns immediately
    // ackmesssage is destroyed here
}

Fix:

1) consider using synchronous writing operation

2) if you want to stay with async you could store ackmessage as data member of session and then pass it as argument to buffer. You need to find some way of extending its lifetime until handler is invoked.

Here is nice example to resolve your issue, create shared_ptr from ackmessage and pass it to your handler - lambda, it extends lifetime of string which is being writing.

rafix07
  • 20,001
  • 3
  • 20
  • 33