使用 boost::asio 通过 UDP 发送结构

Sending structure over UDP using boost::asio

我需要通过 UDP 一次发送不同数据类型的结构。我试过使用 boost 库,但我无法一次发送所有结构元素。这是我需要发送的结构片段:

    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);

这不起作用,因为正在发送其他数据。我只想发送结构的元素,它们之间没有分隔或任何类型的数据。

提前致谢。

那是行不通的。您只能通过连接发送原始数据,因为 ASIO 不执行任何序列化。 std::string 不是一个简单的类型,它还包含对通过连接发送没有意义的成员(如指针)。此外,结构可能无法在不同种类的计算机之间移植。

您将不得不使用诸如 Boost Serialization 库、Protobuffers 或类似库之类的东西;或自己履行类似职责。

通过网络套接字发送和接收结构(无论您使用的是什么类型的套接字,同步或异步 TCP,数据报 UDP)逻辑上类似于文件 read/write。这意味着 - 简单地转储内存方法是行不通的,尤其是当您的结构包含 class/structure 字段或指针时。 通常使用序列化方法,例如您可以将您的结构序列化为一些二进制文件(ASN1、Google Protocol Buffers 等)或文本格式(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;