【问题标题】:Sending and receiving protobuf data over Socket via boost asio通过 Socket 通过 boost asio 发送和接收 protobuf 数据
【发布时间】:2019-10-13 02:22:53
【问题描述】:

我想通过 TCP 套接字将 Protobuf 数据从我的服务器发送到我的客户端。

我测试了我的客户端和服务器,TCP 连接工作正常。

所以我尝试序列化我的数据并使用 streambuf 发送。

在我的服务器中:

void SendData(protobufType data){
        std::ostream ostream(&this->m_streambuf);
        data.SerializeToOstream(&ostream);

        std::cout<<"Send data"<< std::endl;
        boost::asio::write(this->m_socket, this->m_streambuf);
}

在我的客户中:

boost::asio::streambuf response;
boost::asio::read(socket, response);
std::cout<<"Data received"<< std::endl;

我运行了 3 次我的发送函数(我猜我的数据接缝被发送)但我的客户端接缝永远不会获取数据...

【问题讨论】:

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


    【解决方案1】:

    你的客户挂在这条线上

    boost::asio::read(socket, response);
    

    因为上面和

    是一样的
    boost::asio::read(socket, response, boost::asio::tranfer_all());
    

    the documentation 中描述的内容。

    您使用 read 过载,它采用完成条件。这些函子分为三种:transfer_all_ttransfer_exactly_ttransfer_at_least_t。他们每个人都有operator()(),如果读取操作完成,则返回0 - see reference

    transfer_all_t::opeator()() 的代码是:

      template <typename Error>
      std::size_t operator()(const Error& err, std::size_t)
      {
        return !!err ? 0 : default_max_transfer_size;
      }
    

    所以只有在发生错误时才返回 0。

    transfer_at_least_t::operator()() 是:

      template <typename Error>
      std::size_t operator()(const Error& err, std::size_t bytes_transferred)
      {
        return (!!err || bytes_transferred >= minimum_)
          ? 0 : default_max_transfer_size;
      }
    

    如您所见,如果发生错误或至少传输了 minimum_ 个字节,则返回 0。

    如果您知道readtransfer_all 在发生错误时结束,您可以创建此错误以查看读取数据。您可以在服务器端关闭套接字(用于发送操作)或关闭此套接字。然后您可以更改read 调用以获取error_code,您应该会看到文件结束为错误:

    boost::system::error_code ec;
    boost::asio::read(socket,response,ec);
    if (ec)
    {
       cout << ec.message() << endl; // End of file
       // if ec is End of file you can see what data was read into streambuf
    }
    

    您发送一个序列化对象,因此您知道该对象的大小,为什么不使用发送对象大小的方法(例如 4 个字节),然后在此标头之后发送对象的内容。

    在客户端:

    array<char,4> length;
    boost::asio::read(socket,boost::asio::buffer(length));
    int contentLen = /*conversion from length array into integer */
    vector<char> content( contentLen );
    boost::asio::read(socket,boost::asio::buffer(content));
    

    【讨论】:

      猜你喜欢
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 1970-01-01
      • 2014-10-27
      • 2015-07-07
      • 2018-03-31
      相关资源
      最近更新 更多