使用boost庫序列化傳輸對象


  使用boost庫序列化傳輸對象,要用到boost中的Boost.Serialization

(一)編譯boost

並不是說要用到boost都要對boost進行編譯,只有用到以下庫時才需要編譯,剛好我們要用Serialization,所以要進行編譯

The only Boost libraries that must be built separately are:

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 --help

Select 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/prefix

to 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 install

will 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等等……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM