我有一个如下所示的数据结构:
typedef struct { unsigned short m_short1; unsigned short m_short2; unsigned char m_character; } MyDataType;
我想使用boost :: serialization来序列化这个数据结构,然后使用boost :: asio通过TCP / IP传输它,然后让另一个应用程序接收数据并使用相同的boost库对其进行反序列化。 / p>
I'm trying to following boost::serialization tutorial,(as some other SO questions have suggested)但该示例专门用于写入/读取文件,而不是使用boost :: asio的套接字。
我很确定我有适合工作的工具 - 我只是需要帮助才能让它们协同工作。写入套接字与写入文件不一样,对吗?
非常感谢任何建议。谢谢!
答案 0 :(得分:29)
asio文档中有一个很好的序列化example:server.cpp,stock.hpp,connection.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);
答案 1 :(得分:21)
我想我会与那些试图使用Boost序列化C ++ struct
的人分享这个。对于上面给出的示例,要使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;
答案 2 :(得分:6)
对于这样简单的结构,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。
答案 3 :(得分:4)
我原来的回答:
使用来自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中的'serialize'函数。
答案 4 :(得分:1)
您对boost :: archive执行序列化,获取构造函数参数 - 目标流,您将在其中保存数据。您可以使用boost.iostreams库来定义您自己的流,它将通过网络发送数据,而不是文件或只使用asio套接字流(http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/ip__tcp/iostream.html)。这是一个好方法,我们做了类似的事情,但我们有很少的流(zip / encrypt / send),并使用boost iostreams库进行所有操作。
简单和虚拟方式 - 将您的数据存储在临时文件中并发送此文件:)
答案 5 :(得分:1)
可以使用任何流构建boost序列化归档。因此任何oarchive都可以使用任何ostream,任何iarchive都可以使用任何istream。因此,您可以归档到ostringstream,使用asio传输字符串,并从中重新构建数据。
例如,请参阅binary_oarchive here的参考。
答案 6 :(得分:0)
我怀疑你首先要存档到内存,然后将其写入套接字。