使用boost的archive做可变长度的网络消息数据打包
2009-12-16 21:47
531 查看
使用boost的archive做可变长度的网络消息数据打包
目的
在结构体上面可以定义std::string这样的数据,并方便打包与解包
核心
1. boost库提供了非常方便的对像序列化库boost::archive、boost::serialization,通过这两个库我们可以很方便的打包std里面像std::string、std::list这些类型的数据。
2. 打包数据我们当然要使用二进制的方式所以使用boost::archive::binary_iarchive、boost::archive::binary_oarchive。
3. 在真正编写代码的过程中发现这两个类为了序列化出来的数据有版本的区分还在输出的数据最前面加上一些版本信息,为了去除它们,最终我的解决方案是重写这两个类,将输出版本信息这块代码给关闭掉。
4. boost的序列化方法是在结构体上面做一个函数(全局的不提了),如下:
struct data
{
std::string v;
int v2;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & v;
ar & v2;
}
};
程序员总有一个通病“懒”,看到这样的代码就在想能不能将serialize函数给去掉或者让计算机自动生成,分析了很多,最后的解决方法是使用宏来处理在代码里可以看到MSG1、MSG2…MSG9这样的宏,它们就是为了完成这个想法而做的东西,很丑!!!(哪位有好的解决方法请一定要告知我,非常感谢)
5. 为了做到使用更加方便,简单做了MsgPack与MsgUnpack类来做打包与解包工作。
代码
目的
在结构体上面可以定义std::string这样的数据,并方便打包与解包
核心
1. boost库提供了非常方便的对像序列化库boost::archive、boost::serialization,通过这两个库我们可以很方便的打包std里面像std::string、std::list这些类型的数据。
2. 打包数据我们当然要使用二进制的方式所以使用boost::archive::binary_iarchive、boost::archive::binary_oarchive。
3. 在真正编写代码的过程中发现这两个类为了序列化出来的数据有版本的区分还在输出的数据最前面加上一些版本信息,为了去除它们,最终我的解决方案是重写这两个类,将输出版本信息这块代码给关闭掉。
4. boost的序列化方法是在结构体上面做一个函数(全局的不提了),如下:
struct data
{
std::string v;
int v2;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & v;
ar & v2;
}
};
程序员总有一个通病“懒”,看到这样的代码就在想能不能将serialize函数给去掉或者让计算机自动生成,分析了很多,最后的解决方法是使用宏来处理在代码里可以看到MSG1、MSG2…MSG9这样的宏,它们就是为了完成这个想法而做的东西,很丑!!!(哪位有好的解决方法请一定要告知我,非常感谢)
5. 为了做到使用更加方便,简单做了MsgPack与MsgUnpack类来做打包与解包工作。
代码
//msg_binary_iarchive.h #pragma once // 这文件内容是直接复制的boost的binary_iarchive.hpp的内容做了点儿修改 #include <istream> #pragma warning(push) #pragma warning(disable : 4267) #pragma warning(disable : 4996) #include <boost/archive/binary_iarchive_impl.hpp> #include <boost/archive/impl/basic_binary_iprimitive.ipp> #include <boost/archive/impl/basic_binary_iarchive.ipp> #pragma warning(pop) namespace boost { namespace archive { class naked_binary_iarchive : public binary_iarchive_impl< boost::archive::naked_binary_iarchive, std::istream::char_type, std::istream::traits_type > { public: naked_binary_iarchive(std::istream & is, unsigned int flags = 0) : binary_iarchive_impl< naked_binary_iarchive, std::istream::char_type, std::istream::traits_type >(is, flags) {} naked_binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) : binary_iarchive_impl< naked_binary_iarchive, std::istream::char_type, std::istream::traits_type >(bsb, flags) {} }; } // namespace archive } // namespace boost #include <boost/archive/shared_ptr_helper.hpp> namespace boost { namespace archive { class msg_binary_iarchive : public binary_iarchive_impl< boost::archive::msg_binary_iarchive, std::istream::char_type, std::istream::traits_type >, public detail::shared_ptr_helper { public: typedef binary_iarchive_impl< boost::archive::msg_binary_iarchive, std::istream::char_type, std::istream::traits_type > base; msg_binary_iarchive(std::istream & is, unsigned int flags = 0) : binary_iarchive_impl< msg_binary_iarchive, std::istream::char_type, std::istream::traits_type >(is, flags) {} msg_binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) : binary_iarchive_impl< msg_binary_iarchive, std::istream::char_type, std::istream::traits_type >(bsb, flags) {} template<class T> void load_override(T & t, BOOST_PFTO int) { BOOST_MPL_ASSERT_NOT(( boost::is_pointer<T> )); base::load_override(t, 0); } // 这些信息都不要了 void load_override(boost::archive::class_id_optional_type &, int){} void load_override(boost::archive::tracking_type & t, int){t.t = false;} void load_override(boost::archive::version_type & t, int){t.t = 0;} }; } // namespace archive } // namespace boost // required by export BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::msg_binary_iarchive) BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::msg_binary_iarchive)
//msg_binary_oarchive.h #pragma once // 这文件内容是直接复制的boost的binary_oarchive.hpp的内容做了点儿修改 #include <ostream> #pragma warning(push) #pragma warning(disable : 4267) #pragma warning(disable : 4996) #include <boost/archive/binary_oarchive_impl.hpp> #include <boost/archive/impl/basic_binary_oprimitive.ipp> #include <boost/archive/impl/basic_binary_oarchive.ipp> #pragma warning(pop) namespace boost { namespace archive { class msg_binary_oarchive : public binary_oarchive_impl< msg_binary_oarchive, std::ostream::char_type, std::ostream::traits_type > { public: typedef binary_oarchive_impl< msg_binary_oarchive, std::ostream::char_type, std::ostream::traits_type > base; msg_binary_oarchive(std::ostream & os, unsigned int flags = 0) : binary_oarchive_impl< msg_binary_oarchive, std::ostream::char_type, std::ostream::traits_type >(os, flags) {} msg_binary_oarchive(std::streambuf & bsb, unsigned int flags = 0) : binary_oarchive_impl< msg_binary_oarchive, std::ostream::char_type, std::ostream::traits_type >(bsb, flags) {} template<class T> void save_override(T & t, BOOST_PFTO int) { BOOST_MPL_ASSERT_NOT(( boost::is_pointer<T> )); base::save_override(t, 0); } // 这些信息都不要了 void save_override(const boost::archive::class_id_optional_type &, int){} void save_override(const boost::archive::tracking_type &, int){} void save_override(const boost::archive::version_type &, int){} }; typedef msg_binary_oarchive naked_binary_oarchive; } // namespace archive } // namespace boost // required by export BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::msg_binary_oarchive) BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::msg_binary_oarchive)
//MsgBinaryArchive.h #pragma once #include <strstream> #include "boost/serialization/string.hpp" #include "boost/serialization/list.hpp" #include "msg_binary_iarchive.h" #include "msg_binary_oarchive.h" #define MSG1(mn,t1,n1)/ struct mn/ {/ t1 vn1;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & vn1;/ }/ }; #define MSG2(mn,t1,n1,t2,n2)/ struct mn/ {/ t1 n1;/ t2 n2;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ }/ }; #define MSG3(mn,t1,n1,t2,n2,t3,n3)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ }/ }; #define MSG4(mn,t1,n1,t2,n2,t3,n3,t4,n4)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ }/ }; #define MSG5(mn,t1,n1,t2,n2,t3,n3,t4,n4,t5,n5)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ t5 n5;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ ar & n5;/ }/ }; #define MSG6(mn,t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ t5 n5;/ t6 n6;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ ar & n5;/ ar & n6;/ }/ }; #define MSG7(mn,t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ t5 n5;/ t6 n6;/ t7 n7;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ ar & n5;/ ar & n6;/ ar & n7;/ }/ }; #define MSG8(mn,t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7,t8,n8)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ t5 n5;/ t6 n6;/ t7 n7;/ t8 n8;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ ar & n5;/ ar & n6;/ ar & n7;/ ar & n8;/ }/ }; #define MSG9(mn,t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7,t8,n8,t9,n9)/ struct mn/ {/ t1 n1;/ t2 n2;/ t3 n3;/ t4 n4;/ t5 n5;/ t6 n6;/ t7 n7;/ t8 n8;/ t9 n9;/ template<class Archive> void serialize(Archive & ar, const unsigned int version)/ {/ ar & n1;/ ar & n2;/ ar & n3;/ ar & n4;/ ar & n5;/ ar & n6;/ ar & n7;/ ar & n8;/ ar & n9;/ }/ }; class MsgPack { public: MsgPack(): _oa(_os, boost::archive::no_header) {} template <class T> MsgPack& operator & (const T & v) { reset(); _oa & v; return *this; } template <class T> MsgPack& operator << (const T & v) { _oa & v; return *this; } void reset() { _os.freeze(false); _os.seekp(0); _os.seekg(0); } const char* buffer() { return _os.str(); } size_t size() { return _os.pcount(); } private: std::strstream _os; boost::archive::msg_binary_oarchive _oa; }; class MsgUnpack { public: MsgUnpack(): _ia(_is, boost::archive::no_header) {} void reset(const char* buf, size_t size) { if (_is.pcount()) { _is.seekp(0); _is.seekg(0); } _is.write(buf, (std::streamsize)size); } template <class T> MsgUnpack& operator >> (T & v) { _ia & v; return *this; } private: std::strstream _is; boost::archive::msg_binary_iarchive _ia; }; /* 例子 =============================================================================== // 定义一个有两个成员变量的消息结构 MSG2(stTestMsg, float, x, std::string, str); // 定义一个有四个成员变量的消息结构 MSG4(A, std::list<int>, _list, int, _int, std::string, _str, char, _char); void test() { std::string recvMsgBuf; // 发送 { MsgPack msgPack; stTestMsg testmsg = {3.2f,"fdsfd"}; A a; a._char = 'a'; a._int = 343; a._list.push_back(3); a._list.push_back(432); a._str = "test str"; // 打包消息 msgPack & a; // 重置消息缓冲,并打包数据 msgPack << testmsg; // 在当前包后面添加数据 // 可以用这两个玩意儿去发送消息了 const char* msgBuf = msgPack.buffer(); size_t msgSize = msgPack.size(); recvMsgBuf.resize(msgSize); memcpy((char*)recvMsgBuf.c_str(), msgBuf, msgSize); } // 接收 { MsgUnpack msgUnpack; stTestMsg testmsg; A a; // 设置接收到的包数据 msgUnpack.reset(recvMsgBuf.c_str(), recvMsgBuf.size()); // 解包数据到消息结构体内 msgUnpack >> a >> testmsg; } } */
相关文章推荐
- STM32使用DMA从串口读可变长度数据到内存
- 【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目
- 使用select+非阻塞socket写的网络数据转发程序
- lesson 11:使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出。
- linux socket实现网络聊天室(二):使用线程独立收发消息
- 解决windows10网络数据使用量不统计问题以及任务管理器网络数据为0Mbps问题
- sql 数据类型 论可变长度字符串与定长性能差异(my sql版)
- Xcode使用Archive打包,一直在读取iOS Apps,导致速度太慢的解决办法
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- Java_网络编程_使用TCP协议发送及接收数据
- Android使用AsyncTask异步线程网络通信获取数据(get json)
- Volley框架的使用(加载网络图片,加载json数据)
- 使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出。
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- 网络编程中使用float型数据要注意
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- AFNetWorking的两个使用场景(请求网络数据、图片上传)
- 有关TI DSP的一些东西(整理一些网络资源及手册资料)--外设寄存器和CPU控制寄存器、数据类型、中断的使用
- Visual C# 2008+SQL Server 2005 数据库与网络开发-- 7.3 使用ADO .NET处理数据
- 使用JAVA处理中文和英文混合的网络数据流