Boost asio TCP + google proto

757 views Asked by At

I do my first footsteps with boost asio and google proto. I defined a small test message

message Test
{
optional string test=1;
optional int32 value=2;
}

and one async boost asio server which response with the following function:

  void start()
  {
      Test test;
      test.set_test("test");
      test.set_value(44444);
      test.PrintDebugString();

    boost::asio::async_write(socket_, boost::asio::buffer(test.SerializeAsString()),
        boost::bind(&tcp_connection::handle_write, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

my test client is

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>

#include "test.pb.h"


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

int main(int argc, char* argv[])
{
  try
  {
    boost::asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 15000);
    tcp::socket socket(io_service);
    socket.connect(end_point);
    std::string data;

    for (;;)
    {
      boost::array<char, 128> buf;
      boost::system::error_code error;

      size_t len = socket.read_some(boost::asio::buffer(buf), error);

      if (error == boost::asio::error::eof)
      {
         Test test;
         test.ParseFromString(data);
         test.PrintDebugString();
         break; // Connection closed cleanly by peer.
      }
      else if (error)
        throw boost::system::system_error(error); // Some other error.

      data.append(buf.begin(), buf.end());

    }
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

If i call my server with my client a few times i get different outputs:

test: "test"
value: 44444
533 {
}

test: "test"
value: 44444
1644{
}

test: "test"
value: 44444

the last output is as expected the rest is wrong. I dont understand why i get a bigger output then I have on my server :

test: "test"
value: 44444

Anyone has an idea why i get something like "1644{ }" ?

I think my eof is wrong or?

EDIT

message Header
{
 required int32 size=1;
}

new start

  void start()
  {
      boost::asio::async_read(socket_,
                boost::asio::buffer(m_headerData, m_sizeOfHeader),
                boost::bind(&tcp_connection::handle_read_header, this,
                  boost::asio::placeholders::error));
  }

members:

  const size_t m_sizeOfHeader = sizeof(Header::default_instance().SerializeAsString());
  boost::array<char, sizeof(Header::default_instance().SerializeAsString())> m_headerData;



void handle_read_header(const boost::system::error_code& error_code)
{
    if (!error_code)
    {
        Header header;
        header.ParseFromString(std::string(m_headerData.begin(), m_headerData.end()));
        header.PrintDebugString();
    }
    else
    {

        std::cout << error_code.message()<< "ERROR DELETE READ \n";
        delete this;
    }

I tried my header on this way now, but i get following errors:

Operation canceled or Bad file descriptor

My new client sends :

  Header header;
  header.set_size(101);
  boost::asio::write(socket,boost::asio::buffer(header.SerializeAsString())) ;

I think the problem is that the variable m_sizeOfHeader is wrong... on my server side i get 8, and when i print the output of write on client I get 2...

I dont understand why my sizes for the header are not fixed... i just have one required field

1

There are 1 answers

5
dewaffled On BEST ANSWER

You are ignoring number of bytes read (len) and append garbage to data with:

data.append(buf.begin(), buf.end());

try instead:

data.append(buf.begin(), buf.begin() + len);

Also your code will correctly work only if a single message is sent and socket immediately gracefully closed (with shutdown) after that. In more complex scenario you'll need some kind of protocol that allows to determine message bounds. For instance, you can send message size in first two bytes before message and on receiving side first read two bytes with expected message size, then read message body.