使用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等等……