提升asio TCP +谷歌原型

时间:2015-06-10 15:13:47

标签: c++ boost boost-asio protocol-buffers

我用boost asio和google proto做了我的第一步。我定义了一个小测试消息

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

和一个async boost asio服务器,它使用以下函数进行响应:

  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));
  }

我的测试客户端是

#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;
}

如果我用我的客户端呼叫我的服务器几次,我得到不同的输出:

test: "test"
value: 44444
533 {
}

test: "test"
value: 44444
1644{
}

test: "test"
value: 44444

最后的输出是预期的,其余的是错误的。我不明白为什么我在服务器上获得更大的输出:

test: "test"
value: 44444

任何人都知道为什么我会得到像&#34; 1644 {}&#34; ?

我认为我的自我错误还是?

修改

message Header
{
 required int32 size=1;
}

新的开始

  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));
  }

成员:

  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;
    }

我现在以这种方式尝试了我的标题,但我得到以下错误:

操作已取消或文件描述符错误

我的新客户发送:

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

我认为问题是变量m_sizeOfHeader是错误的......在我的服务器端我得到8,当我在客户端打印写入的输出时我得到2 ...

我不明白为什么标题的大小不固定...我只有一个必填字段

1 个答案:

答案 0 :(得分:0)

您忽略了读取的字节数(len)并将垃圾追加到data

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

尝试改为:

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

此外,只有在发送单个消息并且套接字立即正常关闭(使用shutdown)后,您的代码才能正常工作。在更复杂的场景中,您需要某种允许确定消息边界的协议。例如,您可以在消息之前的前两个字节中发送消息大小,在接收方首先读取具有预期消息大小的两个字节,然后读取消息正文。