繁体   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