boost: adresse IPv4 asio et communications UDP

Problème résolu – Voir en bas pour les notes de solution

J’essaie de créer une application simple pour tester un microcontrôleur compatible Ethernet. Tout ce que je veux faire, c’est envoyer et recevoir de petits paquets UDP. Le code utilise boost :: asio pour le réseau et est incroyablement simple. Pour le débogage, j’ai déplacé l’intialisation des constructeurs afin que je puisse vérifier chaque étape. Voici le corps de mes affaires:

boost::system::error_code myError; boost::asio::ip::address_v4 targetIP; targetIP.from_ssortingng("10.1.1.75", myError); // Configure output IP address. HACKHACK--Hardcoded for Debugging std::cout << "GetIP - " << myError.message() << std::endl; std::cout << "IP: " << targetIP << std::endl; boost::asio::ip::udp::endpoint myEndpoint; // Create endpoint on specified IP. myEndpoint.address(targetIP); myEndpoint.port(0x1000); std::cout << "Endpoint IP: " << myEndpoint.address().to_string() << std::endl; std::cout << "Endpoint Port: " << myEndpoint.port() << std::endl; boost::asio::io_service io_service; // Create socket and IO service, bind socket to endpoint. udp::socket socket(io_service); socket.open( myEndpoint.protocol(), myError ); std::cout << "Open - " << myError.message() << std::endl; socket.bind( myEndpoint, myError ); std::cout << "Bind - " << myError.message() << std::endl; char myMessage[] = "UDP Hello World!"; // Send basig string, enable socket level debugging. socket.send(boost::asio::buffer(myMessage, sizeof(myMessage)), boost::asio::socket_base::debug(true), myError); std::cout << "Send - " << myError.message() << std::endl; boost::array recv_buf; // Receive something (hopefully an echo from the uP) udp::endpoint sender_endpoint; size_t len = socket.receive_from( boost::asio::buffer(recv_buf), myEndpoint ); std::cout.write(recv_buf.data(), len); 

L’accroc se produit juste au début. Le address_v4 ne veut pas accepter l’IP que je lui passe. La sortie de cette application est:

 GetIP - The operation completed successfully IP: 0.0.0.0 Endpoint IP: 0.0.0.0 Endpoint Port: 4096 Open - The operation completed successfully Bind - The operation completed successfully Send - A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied 

Je suppose que l’erreur d’envoi résulte du fait que l’ address_v4 n’est pas correctement définie, mais il n’y a aucune raison de penser à une telle chose.

Pour ceux qui jouent à la maison, mon PC est doté de deux cartes Ethernet, dont l’une a été DHCP 10.1.1.7. L’IP cible doit donc être accessible sans aucun routage. J’utilise BOOST 1.46.1 sur Win7 32 bits et MSVS 10. Il échoue également lorsque j’essaie une adresse IP de 127.0.0.1 , corrigez-moi si je me trompe mais cela devrait fonctionner pour un bouclage dans ce contexte?

Modifier avec les mises à jour:

Donc, grâce aux réponses précédentes, j’ai obtenu l’adresse IP dans mon address_v4 , et je n’essaie plus de lier lorsque je voulais me connecter. La section du code modifiée de façon significative est le TX, qui ressemble maintenant à:

  socket.open( targetEndpoint.protocol(), myError ); std::cout << "Open - " << myError.message() << std::endl; char myMessage[] = "UDP Hello World!"; // Send basig string, enable socket level debugging. socket.send_to(boost::asio::buffer(myMessage, sizeof(myMessage)), targetEndpoint, boost::asio::socket_base::debug(true), myError); std::cout << "Send - " << myError.message() << std::endl; 

(J’ai renommé myEndpoint pour qu’il cible Endpoint afin de réduire la confusion …..)

J’ai maintenant l’erreur en essayant d’envoyer:
The attempted operation is not supported for the type of object referenced
Je donnerais mon premier-né pour un message d’erreur informatif à ce stade! L’erreur est cohérente quel que soit le port cible que j’utilise. La seule chose à laquelle je peux penser est que je dois configurer le port source quelque part, mais je ne vois pas comment vous pouvez le faire dans la documentation de boost::asio .

Résolution finale

J’ai réussi à faire ce travail, donc je vais poster les pièges que j’ai trouvés dans une belle liste pour toute personne qui trébuche sur cette réponse avec des problèmes similaires à moi. Je pense que le principal problème était qu’aucun des exemples de boost ne montrait jamais comment se connecter à une adresse IP spécifiée, ils utilisent tous un résolveur. Cela a rendu les exemples beaucoup plus difficiles à comprendre pour moi.

  • Lorsque vous utilisez l’appel from_ssortingng pour convertir une adresse IP texte, utilisez la syntaxe de la première réponse ci-dessous plutôt que la syntaxe ci-dessus!
  • Lors de la configuration du socket UDP, l’ ordre des opérations est crucial! Si vous ne voulez pas le faire dans le constructeur, vous devez:

    1. Ouvrez le socket en utilisant le protocole requirejs.
    2. Liez le socket à un noeud final local qui spécifie le numéro de port UDP source .
    3. Connectez la prise au sharepoint terminaison distant qui spécifie l’IP de destination et le numéro de port.

    Tenter de lier après la connexion entraînera l’échec de la liaison. La transmission fonctionnera très bien, mais vos paquets seront envoyés depuis un numéro de port arbitraire.

  • Utilisez une méthode d’envoi pour transmettre réellement. N’essayez pas d’activer le débogage des données avec boost::asio::socket_base::debug(true) ! Tout ce que ce drapeau semble faire, c’est provoquer des messages d’erreur dans un envoi par ailleurs fonctionnel!

Je voudrais également partager que mon outil de débogage le plus précieux dans tout cet exercice était Wireshark. Peut-être que c’est uniquement parce que j’ai l’habitude d’avoir un CRO ou un parsingur de protocole lorsque je travaille sur des communications comme celle-ci, mais j’ai trouvé que l’affichage des octets sur fil m’a aidé à régler un tas de choses aurait autrement jamais été retrouvé.

Encouragez-vous de votre aide sur les questions de propriété intellectuelle et aidez-moi à faire la différence entre connecter et connecter.

Le problème que vous rencontrez actuellement semble être votre utilisation de cette ligne:

 targetIP.from_ssortingng("10.1.1.75", myError); 

boost::asio::ip::address::from_ssortingng est une fonction statique qui retourne un object ip::address construit. Changez la pour ressembler à ceci:

 targetIP = boost::asio::ip::address::from_ssortingng("10.1.1.75", myError); 

Et votre adresse IP doit être remplie correctement.

En haut de ma tête, vous essayez de lier le socket à un noeud final dont l’adresse est 10.1.1.75, mais cela semble être un noeud final distant? Je suppose que vous souhaitez le lier localement et utiliser send_to, comme c’est le cas avec UDP

Dans cette ligne, il y a une erreur:

 targetIP = boost::asio::ip::address::from_ssortingng("10.1.1.75", myError); 

Vous devriez mettre:

 targetIP = boost::asio::ip::address_v4::from_ssortingng("10.1.1.75", myError); 

et alors targetIP a la bonne valeur!