簡體   English   中英

C++ boost庫反序列化 object 傳過來 TCP 服務器

[英]C++ boost library deSerialize object passed over TCP server

我在 TCP 服務器上收到 object class Command ,並嘗試使用 boost 庫對其進行反序列化(序列化 function 也包含在代碼中)使用以下代碼:

T deSerialize(std::string s) {    //deSerialize
    T t = T();
    std::ifstream ifs(s);
    std::cout << "check \n";

    boost::archive::text_iarchive ia(ifs);   //<==== Not working
    std::cout << "check2 \n";

    ia >> t;
    return t;
}
template <class T>
std::string serialize(T obj) {    //Serialize
    std::ofstream ofs("output");
    {
        boost::archive::text_oarchive oa(ofs);
        oa << obj;
    }
    return "output";
}
...
while (true) {    //recive data from TCP
        std::fstream dataFile("commands.txt", std::ios::in | std::ios::out | std::ios::app);

        recv(sock, buf, sizeof(buf), 0);

        dataFile << buf;

        dataFile.close();

        c = deSerialize<Command>("commands.txt"); // <=== This line makes it break :(


    }
...

有人可以找到問題嗎?

我們也不知道 看來您真的只是不知道如何從電線中讀取內容。 因此,我將向您展示,從我上次為您制作的同一個示例開始。

此外,無需先寫入文件。 直接從流中序列化/反序列化:

template <class T> void my_save(std::ostream& os, T const& obj) {
    boost::archive::text_oarchive oa(os);
    oa << obj;
}

template <class T> T my_load(std::istream& is) {
    boost::archive::text_iarchive ia(is);

    T result;
    ia >> result;
    return result;
}

如果您堅持,您仍然可以使用帶有文件名的重載,並委托給更新的、更通用的接口:

template <class T> void my_save(std::string const& filename, T const& obj) {
    std::ofstream ofs(filename, std::ios::binary);
    return my_save<T>(ofs, obj);
}

template <class T> T my_load(std::string const& filename) {
    std::ifstream ifs(filename, std::ios::binary);
    return my_load<T>(ifs);
}

連接 Sockets

我將在這里展示如何使用同步 Boost Asio,並且沒有任何協議,以最簡單的方式。

客戶

讓我們創建一個連接到 localhost:8989 並讀取Command對象向量的客戶端:

static constexpr uint16_t port = 8989;

void run_client() {
    tcp::iostream conn(tcp::endpoint{{}, port});

    for (auto&& cmd : my_load<Commands>(conn))
        std::cout << "-----\n" << cmd;
}

就這樣。

服務器

為了進行測試,我們還要創建一個服務器,它接受單個 TCP 連接並向其寫入Commands的演示向量。

void run_server() {
    net::io_context ioc;
    tcp::acceptor acc(ioc, {{}, port});
    tcp::iostream conn(acc.accept());

    my_save(conn,
            Commands{
                {'s', 10, 20, "Save"},
                {'q', 21, 31, "Quit"},
                {'l', 32, 42, "Load"},
                {'x', 43, 53, "Exit"},
            });
}

再一次,僅此而已。

把它放在一起

int main() {
    std::thread s(run_server);

    std::this_thread::sleep_for(10ms); // server must be ready

    run_client();

    s.join();
}

該程序在后台運行服務器,然后針對它運行客戶端,像以前一樣打印:

-----
letter: s
x     : 10
y     : 20
button: Save
-----
letter: q
x     : 21
y     : 31
button: Quit
-----
letter: l
x     : 32
y     : 42
button: Load
-----
letter: x
x     : 43
y     : 53
button: Exit

生活在 Coliru

清單以備將來參考:

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/asio.hpp>
#include <fstream>
#include <iostream>

namespace net = boost::asio;
using namespace std::chrono_literals;
using net::ip::tcp;

class Command {
  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive& arch, unsigned) {
        arch& letter& x& y& button;
    }

    char        letter;
    int         x;
    int         y;
    std::string button;

  public:
    Command(char _letter = '\0', int _x = 0, int _y = 0,
            std::string_view _button = {})
        : letter(_letter)
        , x(_x)
        , y(_y)
        , button(_button)
    { }

    char        getLetter() const { return letter; }
    int         getX()      const { return x;      }
    int         getY()      const { return y;      }
    std::string getButton() const { return button; }

    friend std::ostream& operator<<(std::ostream& os, Command const& cmd){
        return os << "letter: " << cmd.letter << "\n" //
                  << "x     : " << cmd.x << "\n"      //
                  << "y     : " << cmd.y << "\n"      //
                  << "button: " << cmd.button << "\n";
    }
};
using Commands = std::vector<Command>;

template <class T> void my_save(std::ostream& os, T const& obj) {
    boost::archive::text_oarchive oa(os);
    oa << obj;
}

template <class T> T my_load(std::istream& is) {
    boost::archive::text_iarchive ia(is);

    T result;
    ia >> result;
    return result;
}

static constexpr uint16_t port = 8989;

void run_client() {
    tcp::iostream conn(tcp::endpoint{{}, port});

    for (auto&& cmd : my_load<Commands>(conn))
        std::cout << "-----\n" << cmd;
}

void run_server() {
    net::io_context ioc;
    tcp::acceptor acc(ioc, {{}, port});
    acc.listen();

    tcp::iostream conn(acc.accept());

    my_save(conn,
            Commands{
                {'s', 10, 20, "Save"},
                {'q', 21, 31, "Quit"},
                {'l', 32, 42, "Load"},
                {'x', 43, 53, "Exit"},
            });
}

int main() {
    std::thread s(run_server);

    std::this_thread::sleep_for(10ms); // server must be ready

    run_client();

    s.join();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM