使用 boost::asio 通过 UDP 发送结构
Posted
技术标签:
【中文标题】使用 boost::asio 通过 UDP 发送结构【英文标题】:Sending structure over UDP using boost::asio 【发布时间】:2019-11-04 11:31:55 【问题描述】:我需要通过 UDP 一次发送不同数据类型的结构。我曾尝试使用 boost 库,但我无法一次发送所有结构元素。这是我需要发送的结构的 sn-p:
struct sample
char a;
char16_t b;
char c;
std::string d;
char e;
;
sample mystruct;
创建一个连接每个元素的字符串对我不起作用,因为我正在发送不应转换为字符串的十六进制值。这是我用来通过套接字发送信息的方法:
sock.send_to(boost::asio::buffer(&mystruct, sizeof(mystruct)), remote, 0, error);
这不起作用,因为正在发送其他数据。我只想发送结构的元素,它们之间没有分隔或任何类型的数据。
提前致谢。
【问题讨论】:
想想std::string
到底是什么...既然它包裹的字符串可以是动态长度的,你认为它是如何实现的?也许使用指针,它只对您当前的进程是本地的(因此同一系统上的另一个进程不能使用,更不用说在远程系统上)?通常您只能“按原样”发送POD 结构,并且您的结构(感谢std::string
的使用)不是 POD。
您的部分问题是您将值与其表示混淆了。例如,您说“我正在发送十六进制值”。但是没有十六进制值这样的东西。 “十”、“10”、“人类通常拥有的手指数”和“0xA”都以不同的方式表示完全相同的值。十六进制是一种表示值的方式。这些完全相同的值可以用不同的方式表示。
【参考方案1】:
通过网络套接字发送和接收结构(无论您使用什么类型的套接字,同步或异步 TCP,数据报 UDP)逻辑类似于文件读/写。这意味着 - 简单地转储内存方法是行不通的,尤其是当您的结构包含类/结构字段或指针时。 通常使用序列化方法,例如您可以将您的结构序列化为一些二进制(ASN1、Google 协议缓冲区等)或文本格式(XML、JSON、YAML 等) - 通过网络发送结果,接收它并反序列化回结构。
您可以使用boost serialization 进行序列化提议。
即类似:
#include <boost/archive/text_oarchive.hpp>
....
struct sample
char a;
char16_t b;
char c;
std::string d;
char e;
;
namespace boost
namespace serialization
template<class Archive>
void serialize(Archive & ar,const sample& value, const unsigned int version)
ar & value.a;
ar & value.b;
ar & value.c;
ar & value.d;
ar & value.e;
// namespace serialization
// namespace boost
...
sample mystruct;
....
std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
archive << mystruct;
...
sock.send_to( boost::asio::buffer(archive_stream.str()), remote, 0, error);
然后你可以在收到时反序列化结构
#include <boost/archive/text_iarchive.hpp>
....
std::string str;
str.resize(1024);
boost::asio::udp::endpoint sender_endpoint;
std::size_t len = socket.receive_from(
boost::asio::buffer(str), sender_endpoint);
....
std::istringstream archive_stream(str);
sample mystruct;
boost::archive::text_iarchive archive(archive_stream);
archive >> mystruct;
【讨论】:
【参考方案2】:那是行不通的。您只能通过连接发送原始数据,因为 ASIO 不执行任何序列化。 std::string
不是普通类型,还包含通过连接发送没有意义的成员(如指针)。此外,一个结构可能无法在不同种类的计算机之间移植。
您将不得不使用诸如 Boost 序列化库、Protobuffers 或类似库之类的东西;或自己执行类似的职责。
【讨论】:
以上是关于使用 boost::asio 通过 UDP 发送结构的主要内容,如果未能解决你的问题,请参考以下文章
如何拆分接收到的 boost asio udp 套接字联合数据报