vint
vint

Reputation: 161

streambuf with boost::asio::async_write

Tell me how to use boost::asio::streambuf with boost::asio::async_write. I have a server application that connects to it one client.

For each connection I create object tcp_connection.

How do I properly create buffer for sending data if I need to send to the client several consecutive messages?

Do I need to have to synchronize calls Send() because it is they use a global buffer to be sent? Or do I need to create a separate buffer before calling async_write?

For example, in Windows using IOCP I create my own OVERLAPPED structure containing buffer. I create a buffer before calling WSASend and delete after the operation is completed, extracting it from the OVERLAPPED Structure. Ie for each WSASend has a own buffer.

And how to do to boost::asio::async_write?

Here I have a class tcp_connection

#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/bind.hpp>
#include <iostream>

class tcp_connection
    // Using shared_ptr and enable_shared_from_this Because we want to keep the
    // tcp_connection object alive As long as there is an operation that refers to
    // it.
    : public boost::enable_shared_from_this<tcp_connection> {

    tcp_connection(boost::asio::io_service& io) : m_socket(io) {}

    void send(std::string data) {
        {
            std::ostream stream(&send_buffer);
            stream << data;
        }

        std::cout << "Send Data   =" << data                     << std::endl;
        std::cout << "Send Buffer =" << make_string(send_buffer) << std::endl;

        boost::asio::async_write(m_socket, send_buffer,
                                 boost::bind(&tcp_connection::handle_send, this, 
                                     boost::asio::placeholders::error,
                                     boost::asio::placeholders::bytes_transferred));
    }
    void handle_send(const boost::system::error_code &error, size_t);

  private:
    static std::string make_string(boost::asio::streambuf const&) { return "implemented elsewhere"; }
    boost::asio::ip::tcp::socket m_socket;
    boost::asio::streambuf send_buffer;
};

Upvotes: 3

Views: 3666

Answers (2)

sehe
sehe

Reputation: 392893

If the buffer is local to the connection and you don't access it in other threads, you don't need to lock or copy. That's no different than anywhere without using Asio.

You do need to synchronize operations on the same socket: Why do I need strand per connection when using boost::asio?

To send the whole buffer just use boost::asio::async_write.

Note: you should probably use shared_from_this() instead of this in the bind for the completion handler

Upvotes: 1

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

Be really careful with async_write, you should not overlap async_writes to the same stream (see the spec http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/reference/async_write/overload1.html). I am not sure that you really need asynchronous writes as long as you don't need to transfer so many data and doing other things in parallel... If you really need it, then you should ensure the synchronization. You may use some locking mechanism, acquire a lock before (async) writing and unlock in the WriteHandler.

Upvotes: 1

Related Questions