在接收端读取序列化结构 boost asio
Reading a serialized struct at the receiver end boost asio
我是提升和网络新手 ;)。我正在使用 boost::asio 制作客户端服务器应用程序,我需要将结构作为消息传递,因此使用 boost::asio::serialization
:
test.h
#pragma once
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
struct Test
{
public:
int a;
int b;
template<typename archive> void serialize(archive& ar, const unsigned version) {
ar & a;
ar & b;
}
};
客户端发送:
void send_asynchronously(tcp::socket& socket) {
Test info;
info.a = 1;
info.b = 2;
{
std::ostream os(&buf);
boost::archive::binary_oarchive out_archive(os);
out_archive << info;
}
async_write(socket, buf, on_send_completed);
}
在接收方,我将数据读入 boost::asio::buffer
,我想知道一种解析此缓冲区并在服务器端提取对象的方法。请帮忙。
您没有显示足够的代码来了解您如何声明 buf
或管理生命周期。
我假设您使用了 boost::asio::streambuf buf;
并且它具有静态存储持续时间(命名空间范围)或者是 class 成员(但您没有显示 class)。
无论哪种方式,无论你有什么,你都可以"the same"反向接收。
这是一个简化版本(省略了异步,因此我们不必像我上面提到的那样猜测生命周期);
连接
让我们在本地主机的 3001 端口连接到一个假想的服务器(我们可以在下面创建一个):
asio::io_context ioc;
asio::streambuf buf;
tcp::socket s(ioc, tcp::v4());
s.connect({{}, 3001});
序列化
基本上你所拥有的:
{
std::ostream os(&buf);
boost::archive::binary_oarchive oa(os);
Test req {13,31};
oa << req;
}
注意 stream/archive 周围的 {} 范围,确保归档在发送前完成。
发送
/*auto bytes_sent =*/ asio::write(s, buf);
收到
假设我们的服务器发回另一个 Test
以相同方式序列化的对象¹。
读入缓冲区,假设没有帧,我们将 "read until the end of the stream":
boost::system::error_code ec;
/*auto bytes_received =*/ asio::read(s, buf, ec);
if (ec && ec != asio::error::eof) {
std::cout << "Read error: " << ec.message() << "\n";
return 1;
}
In real life you want timeouts and limits to the amount of data read. Often your protocol will add framing where you know what amount of data to read or what boundary marker to expect.
反序列化
Test response; // uninitialized
{
std::istream is(&buf);
boost::archive::binary_iarchive ia(is);
ia >> response;
}
完整演示
#include <boost/asio.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <iostream>
namespace asio = boost::asio;
using tcp = boost::asio::ip::tcp;
struct Test {
int a,b;
template<typename Ar> void serialize(Ar& ar, unsigned) { ar & a & b; }
};
int main() {
asio::io_context ioc;
asio::streambuf buf;
tcp::socket s(ioc, tcp::v4());
s.connect({{}, 3001});
///////////////////
// send a "request"
///////////////////
{
std::ostream os(&buf);
boost::archive::binary_oarchive oa(os);
Test req {13,31};
oa << req;
}
/*auto bytes_sent =*/ asio::write(s, buf);
/////////////////////
// receive "response"
/////////////////////
boost::system::error_code ec;
/*auto bytes_received =*/ asio::read(s, buf, ec);
if (ec && ec != asio::error::eof) {
std::cout << "Read error: " << ec.message() << "\n";
return 1;
}
Test response; // uninitialized
{
std::istream is(&buf);
boost::archive::binary_iarchive ia(is);
ia >> response;
}
std::cout << "Response: {" << response.a << ", " << response.b << "}\n";
}
使用 netcat 模拟具有先前生成的响应的服务器 Test{42,99}
(此处使用 base64 编码):
base64 -d <<<"FgAAAAAAAABzZXJpYWxpemF0aW9uOjphcmNoaXZlEgAECAQIAQAAAAAAAAAAKgAAAGMAAAA=" | nc -N -l -p 3001
它打印:
Response: {42, 99}
¹ 在相同的体系结构上并使用相同版本的 boost 编译,因为 Boost 的二进制存档不可移植。 live demo 很好地证明了这个
我是提升和网络新手 ;)。我正在使用 boost::asio 制作客户端服务器应用程序,我需要将结构作为消息传递,因此使用 boost::asio::serialization
:
test.h
#pragma once
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
struct Test
{
public:
int a;
int b;
template<typename archive> void serialize(archive& ar, const unsigned version) {
ar & a;
ar & b;
}
};
客户端发送:
void send_asynchronously(tcp::socket& socket) {
Test info;
info.a = 1;
info.b = 2;
{
std::ostream os(&buf);
boost::archive::binary_oarchive out_archive(os);
out_archive << info;
}
async_write(socket, buf, on_send_completed);
}
在接收方,我将数据读入 boost::asio::buffer
,我想知道一种解析此缓冲区并在服务器端提取对象的方法。请帮忙。
您没有显示足够的代码来了解您如何声明 buf
或管理生命周期。
我假设您使用了 boost::asio::streambuf buf;
并且它具有静态存储持续时间(命名空间范围)或者是 class 成员(但您没有显示 class)。
无论哪种方式,无论你有什么,你都可以"the same"反向接收。
这是一个简化版本(省略了异步,因此我们不必像我上面提到的那样猜测生命周期);
连接
让我们在本地主机的 3001 端口连接到一个假想的服务器(我们可以在下面创建一个):
asio::io_context ioc;
asio::streambuf buf;
tcp::socket s(ioc, tcp::v4());
s.connect({{}, 3001});
序列化
基本上你所拥有的:
{
std::ostream os(&buf);
boost::archive::binary_oarchive oa(os);
Test req {13,31};
oa << req;
}
注意 stream/archive 周围的 {} 范围,确保归档在发送前完成。
发送
/*auto bytes_sent =*/ asio::write(s, buf);
收到
假设我们的服务器发回另一个 Test
以相同方式序列化的对象¹。
读入缓冲区,假设没有帧,我们将 "read until the end of the stream":
boost::system::error_code ec;
/*auto bytes_received =*/ asio::read(s, buf, ec);
if (ec && ec != asio::error::eof) {
std::cout << "Read error: " << ec.message() << "\n";
return 1;
}
In real life you want timeouts and limits to the amount of data read. Often your protocol will add framing where you know what amount of data to read or what boundary marker to expect.
反序列化
Test response; // uninitialized
{
std::istream is(&buf);
boost::archive::binary_iarchive ia(is);
ia >> response;
}
完整演示
#include <boost/asio.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <iostream>
namespace asio = boost::asio;
using tcp = boost::asio::ip::tcp;
struct Test {
int a,b;
template<typename Ar> void serialize(Ar& ar, unsigned) { ar & a & b; }
};
int main() {
asio::io_context ioc;
asio::streambuf buf;
tcp::socket s(ioc, tcp::v4());
s.connect({{}, 3001});
///////////////////
// send a "request"
///////////////////
{
std::ostream os(&buf);
boost::archive::binary_oarchive oa(os);
Test req {13,31};
oa << req;
}
/*auto bytes_sent =*/ asio::write(s, buf);
/////////////////////
// receive "response"
/////////////////////
boost::system::error_code ec;
/*auto bytes_received =*/ asio::read(s, buf, ec);
if (ec && ec != asio::error::eof) {
std::cout << "Read error: " << ec.message() << "\n";
return 1;
}
Test response; // uninitialized
{
std::istream is(&buf);
boost::archive::binary_iarchive ia(is);
ia >> response;
}
std::cout << "Response: {" << response.a << ", " << response.b << "}\n";
}
使用 netcat 模拟具有先前生成的响应的服务器 Test{42,99}
(此处使用 base64 编码):
base64 -d <<<"FgAAAAAAAABzZXJpYWxpemF0aW9uOjphcmNoaXZlEgAECAQIAQAAAAAAAAAAKgAAAGMAAAA=" | nc -N -l -p 3001
它打印:
Response: {42, 99}
¹ 在相同的体系结构上并使用相同版本的 boost 编译,因为 Boost 的二进制存档不可移植。 live demo 很好地证明了这个