1

I have client-server application. I have no trouble when I sent a few KBs of data, but when the data grow to 2-4 MB data transfer speed was extremely reduced. I modified an example and use text_archive(because of this) to serialize my data structures, but its didn't help me. It appears that to write 2-4 MB to text_archive takes 6-7 seconds, and read from text_archive takes 10-18 seconds. My structs consisted of few vectors and had more data, but common implementation looked like this:

template <typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  {
    ar & code;
    ar & name;
    ...
  }

But why it takes so long? I have no idea. I was obliged to reject this approach.

I searched the solution, and probably I found it. It is std::istream/ostream. But my implementation seems a kind of crutch. Here is my code:

class connection
{
private:
  /// The underlying socket.
  boost::asio::ip::tcp::socket socket_;

  /// binary stream in
  boost::asio::streambuf readStreambuf;
  std::istream readStream;

  /// binary stream out
  boost::asio::streambuf writeStreambuf;
  std::ostream writeStream;
public:
  /// Constructor.
  connection(boost::asio::io_service& io_service)
      : socket_(io_service), readStream(&readStreambuf), writeStream(&writeStreambuf)
  {

  }

  ...

  /// Asynchronously write a data structure to the socket.
  template <typename T, typename Handler>
  void async_write(const T& t, Handler handler)
  {
      writeStream.clear();
      writeStream << t;
      writeStream << "Close connection \r\n\r\n";

      //is it make sense?     
      socket_.set_option(boost::asio::ip::tcp::no_delay(true));
      boost::system::error_code ec;
      socket_.set_option(boost::asio::socket_base::send_buffer_size(1024 * 1024 * 5), ec);
      //

      boost::asio::async_write(socket_, writeStreambuf, handler);
  }

  /// Asynchronously read a data structure from the socket.
  template <typename T, typename Handler>
  void async_read(T& t, Handler handler)
  {
      void (connection::*func)(const boost::system::error_code&, T&, boost::tuple<Handler>) = &connection::handle_read_stream<T, Handler>;

      boost::asio::async_read_until(socket_, readStreambuf, "Close connection \r\n\r\n", boost::bind(func, this, boost::asio::placeholders::error, boost::ref(t), boost::make_tuple(handler)));
  }

  template <typename T, typename Handler>
  void handle_read_stream(const boost::system::error_code& e,
      T& t, boost::tuple<Handler> handler)
  {
      if (e)
      {
          boost::get<0>(handler)(e);
      }
      else
      {
          try
          {
              readStream.clear();
              readStream >> t;
          }
          catch (std::exception& e)
          {
              // Unable to decode data.
              boost::system::error_code error(boost::asio::error::invalid_argument);
              boost::get<0>(handler)(error);
              return;
          }

          // Inform caller that data has been received ok.
          boost::get<0>(handler)(e);
      }
  }

writeStream << t and readStream >> t works pretty fast, but I have a bad feeling about writeStream << "Close connection \r\n\r\n". Is it right? It works, but I think it works wrong. Should I pass the number of bytes instead? But how? How do it properly?

Community
  • 1
  • 1
Deachy
  • 13
  • 1
  • 4
  • I am confused. So, with the new approach you do not have any performance issue and the only thing you want to check is whether `writeStream << "Close connection \r\n\r\n";` is correct? It is correct. – Arunmu Nov 12 '16 at 06:50
  • In the past I had complete expression "\r\n". There, is potentialy error is exist. It appears, on client side, socket was closing connection because he is really found complete expression. How it can be? I don't know, I decided to make more complex complete expression and now I have working like application. My question is how to properly read/write (not error prone) to std stream, because this approach may be dead end. – Deachy Nov 12 '16 at 20:14

0 Answers0