J'ai besoin d'envoyer une structure de différents types de données à la fois via UDP. J'ai essayé d'utiliser la bibliothèque boost, mais je ne peux pas envoyer tous les éléments de structure en même temps. Voici un extrait de la structure que je dois envoyer:

    struct sample {
       char a;
       char16_t b;
       char c;
       std::string d;
       char e;
    };
    sample mystruct;

La création d'une chaîne concaténant chaque élément ne fonctionne pas pour moi car j'envoie des valeurs hexadécimales qui ne doivent pas être converties en chaîne. Voici la méthode que j'utilise pour envoyer les informations via le socket:

sock.send_to(boost::asio::buffer(&mystruct, sizeof(mystruct)), remote, 0, error);

Cela ne fonctionne pas car des données supplémentaires sont envoyées. Je veux seulement envoyer les éléments de la structure, sans séparation ni aucune sorte de données entre eux.

Merci d'avance.

1
Javier Urrestarazu 4 nov. 2019 à 14:31

2 réponses

Envoi et réception de structures sur des sockets réseau (peu importe le type de socket que vous utilisez TCP synchrone ou asynchrone, UDP datagramme) logique similaire à la lecture / écriture de fichier. Cela signifie que le simple fait de vider l'approche de la mémoire ne fonctionnera pas, surtout lorsque votre structure contient des champs de classe / structure ou des pointeurs. L'approche de sérialisation est généralement utilisée à la place, par ex. vous pouvez sérialiser votre structure dans un format binaire (ASN1, Google Protocol Buffers, etc.) ou texte (XML, JSON, YAML, etc.) - envoyer le résultat par réseau, le recevoir et désérialiser à nouveau vers une structure.

Vous pouvez utiliser booster la sérialisation pour la sérialisation propose.

C'est à dire. quelque chose comme:

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

Ensuite, vous pouvez désérialiser la structure, une fois reçue

#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
Victor Gubin 4 nov. 2019 à 12:31

Cela ne fonctionnera pas. Vous ne pouvez envoyer des données brutes que via une connexion car ASIO n'effectue aucune sérialisation. std::string n'est pas un type trivial et contient également des membres (comme des pointeurs) qui n'ont pas de sens à envoyer via une connexion. En outre, une structure peut ne pas être portable entre des ordinateurs de types différents.

Vous devrez utiliser quelque chose comme la bibliothèque Boost Serialization, Protobuffers ou une bibliothèque similaire; ou effectuer vous-même des tâches similaires.

0
Acorn 4 nov. 2019 à 11:41