使用boost库序列化传输对象,要用到boost中的Boost.Serialization
(一)编译boost
并不是说要用到boost都要对boost进行编译,只有用到以下库时才需要编译,刚好我们要用Serialization,所以要进行编译
The only Boost libraries that must be built separately are:
- Boost.Filesystem
- Boost.GraphParallel
- Boost.IOStreams
- Boost.MPI
- Boost.ProgramOptions
- Boost.Python (see the Boost.Python build documentation before building and installing it)
- Boost.Regex
- Boost.Serialization
- Boost.Signals
- Boost.System
- Boost.Thread
- Boost.Wave
A few libraries have optional separately-compiled binaries:
- Boost.DateTime has a binary component that is only needed if you're using its to_string/from_string or serialization features, or if you're targeting Visual C++ 6.x or Borland.
- Boost.Graph also has a binary component that is only needed if you intend to parse GraphViz files.
- Boost.Math has binary components for the TR1 and C99 cmath functions.
- Boost.Random has a binary component which is only needed if you're using random_device.
- Boost.Test can be used in “header-only” or “separately compiled” mode, although separate compilation is recommended for serious use.
那怎么对boost进行编译呢:
Issue the following commands in the shell (don't type $; that represents the shell's prompt):
$ cd path/to/boost_1_51_0
$ ./bootstrap.sh --helpSelect your configuration options and invoke ./bootstrap.sh again without the --help option. Unless you have write permission in your system's /usr/local/ directory, you'll probably want to at least use
$ ./bootstrap.sh --prefix=path/to/installation/prefixto install somewhere else. Also, consider using the --show-libraries and --with-libraries=library-name-list options to limit the long wait you'll experience if you build everything. Finally,
$ ./b2 installwill leave Boost binaries in the lib/ subdirectory of your installation prefix. You will also find a copy of the Boost headers in the include/ subdirectory of the installation prefix, so you can henceforth use that directory as an #include path in place of the Boost root directory.
选择一个路径,把prefix改成你想要的文件夹名,这样就把boost库编译到了那个文件夹中了(编译的过程大概要用10分钟吧)
然后在/usr/lib创建一个软链接
ln -s /home/lei/mylib/prefix/lib/libboost_serialization.so /usr/lib/libboost_serialization.so
ln -s /home/lei/mylib/prefix/lib/libboost_system.so.1.51.0 /usr/lib/libboost_system.so.1.51.0
注意这时要用到上面两个动态链接库
这样编译时加上-lboost_serialization 同时包含相应的头文件,就可以boost中用来序列化的库了~~
更多资料:boost库网站上的介绍
(二)编写自己的消息结构
以下是我编写的一个简单的消息结构
#ifndef MESSAGE_H #define MESSAGE_H #include <string> //serialization #include <boost/archive/text_oarchive.hpp> //deserialization #include <boost/archive/text_iarchive.hpp> using std::string; //message type enum MessageOption { Login, Logout, SendToAll, PrivateChat }; struct Message { friend class boost::serialization::access; //use this function to serialize and deserialize object template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & sender & receiver & message & option; } string sender; string receiver; string message; MessageOption option; }; #endif
注意编写class或者struct时要编写serialize函数
接下来是序列化与反序列化的方法
#ifndef SERIALIZE_H #define SERIALIZE_H #include <string> #include "Message.h" class Serialization { public: static std::string Serialize(const Message& msg); static Message DeSerialize(const std::string& message); }; #endif
#include "Serialization.h" #include <sstream> std::string Serialization::Serialize(const Message& msg) { std::ostringstream archiveStream; boost::archive::text_oarchive archive(archiveStream); archive<<msg; return archiveStream.str(); } Message Serialization::DeSerialize(const std::string& message) { Message msg; std::istringstream archiveStream(message); boost::archive::text_iarchive archive(archiveStream); archive>>msg; return msg; }
(三)处理消息
刚才编写的那个消息结构里面有个option,通过这个option我们就可以知道这个对方发过来的消息是要干嘛的
以下是服务器处理客户端消息的函数
template<typename T> void EpollServerSocket<T>::ProcessMessage(Socket& clientSocket) { std::string message; ReceiveMessage(clientSocket,message); T msgStruct=Serialization::DeSerialize(message); switch(msgStruct.option) { case Login : SendMessage(clientSocket,"Login_Success"); break; case Logout: SendMessage(clientSocket,"Logout_Success"); DeleteClient(clientSocket.GetSocketfd()); break; case SendToAll: SendToAllUsers(msgStruct.message); break;
//messages of other type……
default: break;
} }
通过switch语句来判断消息的类型,个人觉得还是比较简洁的
boost库中有很多东西可以学习,像asio(Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型。)
以及还有智能指针shared_ptr等等……