提升 asio TCP + google proto

Boost asio TCP + google proto

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

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

和一个异步增强 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

有人知道为什么我会得到类似“1644{ }”的信息吗?

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

编辑

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;
  header.set_size(101);
  boost::asio::write(socket,boost::asio::buffer(header.SerializeAsString())) ;

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

我不明白为什么 header 的尺码不固定...我只有一个必填字段

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

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

试试看:

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

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