[英]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);
}
我將在這里展示如何使用同步 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
清單以備將來參考:
#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.