【问题标题】:Serializing binary data in boost fails with `invalid signature' error在 boost 中序列化二进制数据失败并出现“无效签名”错误
【发布时间】:2013-05-18 06:15:02
【问题描述】:

我很难找出使用 boost 序列化/asio 通过网络发送对象的正确方法。 message 类尽可能简单。它对 C++ 不友好,也不适合我的需求,我只是暂时保持简单以测试 asio/ser:

class message {
    friend class boost::serialization::access;
public:
    message(){}
    int type;
    int sender;
    int assignment;
    int nogood;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & type;
        ar & sender;
        ar & assignment;
        ar & nogood;
    }
};

在客户端,当代理决定发送消息时,通过它的 tcp 连接将其发送到服务器:

message m;
// do something to generate message
boost::asio::streambuf bufx;
std::ostream os( &bufx );
boost::archive::binary_oarchive ar( os );
ar & m;
boost::asio::write( socket, bufx);

服务器端代码:

boost::asio::streambuf bufx;
std::istream is(&bufx);
boost::archive::binary_iarchive ia(is);  // <--- Exception: invalid signature
size_t rcx = asio::read(socket,bufx);
message m;
ia >> m;

【问题讨论】:

    标签: c++ boost boost-asio boost-serialization


    【解决方案1】:

    我遇到了同样的异常。

    This official example 帮助了我。

    如果您仍然遇到问题,请尝试此操作。

    size_t n = sock.receive(bufs);
    
    // received data is "committed" from output sequence to input sequence
    b.commit(n);
    
    std::istream is(&b);
    std::string s;
    is >> s;
    

    就我而言,我使用 async_read。其实我修改了example

      boost::asio::streambuf inbound_;
      boost::asio::streambuf::mutable_buffers_type bufs = inbound_.prepare(inbound_data_size);
      void (connection::*f)(
          const boost::system::error_code&, std::size_t,
          T&, boost::tuple<Handler>)
        = &connection::handle_read_data<T, Handler>;
      boost::asio::async_read(socket_, boost::asio::buffer(bufs), 
        boost::bind(f, this,
          boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(t), handler));
    

    然后在处理程序处

      /// Handle a completed read of message data.
      template <typename T, typename Handler>
      void handle_read_data(const boost::system::error_code& e, std::size_t bytes_transferred,
          T& t, boost::tuple<Handler> handler)
      {
        if (e)
        {
          boost::get<0>(handler)(e);
        }
        else
        {
          // Extract the data structure from the data just received.
          try
          {
            inbound_.commit(bytes_transferred);
            std::istream archive_stream(&inbound_);
            boost::archive::binary_iarchive archive(archive_stream);
            archive >> t;
          }
          catch (std::exception& err)
          {
            // 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);
        }
      }
    

    【讨论】:

      【解决方案2】:

      在您的服务器端代码中,当您创建二进制存档时,streambuf 为空。如果存档构造函数在存档的开头寻找一个幻数,那么它不会找到它。尝试在构造流和存档之前调用boost::asio::read() 填充streambuf

      【讨论】:

      • 感谢您的回答。我在streambuf 定义之后立即移动了read()。现在 read 会抛出异常并显示此消息:End of file
      • 我相信这是意料之中的。 read() 阻塞,直到缓冲区已满或发生错误。在这种情况下,“错误”是套接字已关闭。您可能希望使用 read() overload 通过 boost::system::error_code 引用参数返回状态,而不是抛出错误。
      猜你喜欢
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      相关资源
      最近更新 更多