23

我有一个看起来像这样的数据结构:

类型定义结构
{
  无符号短 m_short1;
  无符号短 m_short2;
  无符号字符 m_character;
} 我的数据类型;

我想使用 boost::serialization 序列化这个数据结构,然后使用 boost::asio 通过 TCP/IP 传输它,然后让另一个应用程序接收数据并使用相同的 boost 库对其进行反序列化。

我正在尝试遵循 boost::serialization 教程,(正如其他一些 SO 问题所建议的那样),但该示例专门用于写入/读取文件,而不是使用 boost::asio 的套接字。

我很确定我有合适的工具来完成这项工作——我只需要帮助让它们一起工作。写入套接字与写入文件没有什么不同,对吧?

任何建议都非常感谢。谢谢!

4

7 回答 7

31

asio 文档中有一个很好的序列化示例: server.cppstock.hppconnection.hpp

这是一个片段:

std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
archive << your_struct;
outbound_data_ = archive_stream.str();
boost::asio::async_write(socket_, 
    boost::asio::buffer(outbound_data_), handler);
于 2009-03-16T21:54:20.070 回答
27

我想我会与任何尝试struct使用 Boost 序列化 C++ 的人分享这个。对于上面给出的示例,要使struct序列化,您将添加一个serialize函数:

typedef struct
{
  unsigned short m_short1;
  unsigned short m_short2;
  unsigned char m_character;

  template <typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  {
    ar & m_short1;
    ar & m_short2;
    ar & m_character;
  }
} MyDataType;
于 2011-07-26T20:25:50.690 回答
5

对于这种简单的结构,boost::serialization 是矫枉过正和巨大的开销。

做更简单的:

vector<uint16_t> net(3,0);

net[0]=htons(data.m_short1);
net[1]=htons(data.m_short2);
net[2]=htons(data.character);

asio::async_write(socket,buffer((char*)&net.front(),6),callback);

vector<uint16_t> net(3,0);
asio::async_read(socket,buffer((char*)&net.front(),6),callback);

callback:
data.m_short1=ntohs(net[0]);
data.m_short2=ntohs(net[1]);
data.character=ntohs(net[2]);

并且为自己节省了 boost::serialization 的巨大开销

而且,如果您使用具有相同字节顺序的计算机工作(大/小)的私有协议,它只是按原样发送结构--POD。

于 2009-03-18T11:44:43.350 回答
4

编辑:我在下面收回我的答案,我提出的确实比 stringstream 解决方案具有时间和空间优势,但 asio::stream API 缺少一些长期需要的重要功能(例如定时中断)。


我原来的答案:

使用来自 boost::asio 的流,与将其写入 std::stringstreams 然后一次性发送相比,它具有时间和空间优势。方法如下:

客户端代码:

boost::asio::ip::tcp::iostream stream("localhost", "3000");

if (!stream)
  throw std::runtime_error("can't connect");

服务器代码:

boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint
  = boost::asio::ip::tcp::endpoint(ip::tcp::v4(), 3000);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
boost::asio::ip::tcp::iostream stream;

// Your program stops here until client connects.
acceptor.accept(*stream.rdbuf()); 

然后,在您连接到客户端或服务器流之后,只需执行以下操作:

MyDataType obj;

// Send the object.
boost::archive::text_oarchive archive(stream);
archive << obj;

// Or receive it.
boost::archive::text_iarchive archive(stream);
archive >> obj;

正如 Tymek 在他的回答中所写,您当然需要将“序列化”功能添加到您的 MyDataType 中。

于 2011-11-21T23:05:08.460 回答
1

您对获取构造函数参数的 boost::archive 进行序列化 - 目标流,您将在其中保存数据。您可以使用 boost.iostreams 库来定义您自己的流,它将通过网络发送数据,而不是文件或仅使用 asio 套接字流(http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/参考/ip__tcp/iostream.html)。这是一个好方法,我们在这方面做了类似的事情,但是我们的流(zip/encrypt/send)很少,并且所有操作都使用了 boost iostreams 库。

简单而虚拟的方式 - 将您的数据存储在临时文件中并发送此文件:)

于 2009-03-16T21:50:11.000 回答
1

boost 序列化档案可以用任何流构建。因此,任何 oarchive 都可以使用任何 ostream,任何 iarchive 都可以使用任何 istream。因此,您可以归档到 ostringstream,使用 asio 传输字符串,并从中重建数据。

例如,请参见 binary_oarchive here的参考。

于 2009-03-16T22:08:37.290 回答
-1

我怀疑您首先要存档到内存,然后将其写入套接字。

于 2009-03-16T21:56:21.937 回答