Отправка структуры по UDP с использованием boost :: asio - PullRequest
1 голос
/ 04 ноября 2019

Мне нужно отправить структуру разных типов данных одновременно через UDP. Я попытался использовать библиотеку наддува, но я не могу отправить все элементы структуры одновременно. Вот фрагмент структуры, которую мне нужно отправить:

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

Это не работает, потому что есть дополнительные данные, которые отправляются. Я только хочу отправить элементы структуры, без разделения или каких-либо данных между ними.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 04 ноября 2019

Отправка и получение структур через сетевые сокеты (независимо от того, какой тип сокета вы используете для синхронного или асинхронного TCP, датаграмма UDP) логически аналогичны чтению / записи файла. Это означает, что простой дамп памяти не сработает, особенно если ваша структура содержит поля или указатели класса / структуры. Вместо этого обычно используется подход сериализации, например, вы можете сериализовать свою структуру в некоторый двоичный (ASN1, буфер протокола Google и т. Д.) Или текстовый формат (XML, JSON, YAML и т. Д.) - отправьте результат по сети, получите его и удалите сериализацию обратно вструктура.

Вы можете использовать повышение сериализации для предложения сериализации.

Т.е. что-то вроде:

#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 & g.c;
    ar & g.d;
    ar & g.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;
0 голосов
/ 04 ноября 2019

Это не сработает. Вы можете отправлять необработанные данные только через соединение, поскольку ASIO не выполняет сериализацию. std::string не является тривиальным типом и также содержит элементы (например, указатели), которые не имеют смысла отправлять через соединение. Кроме того, структура не может быть переносимой между компьютерами разных типов.

Вам придется использовать что-то вроде библиотеки Boost Serialization, Protobuffers или аналогичной библиотеки;или выполняйте аналогичные обязанности самостоятельно.

...