boost:asio IPv4-Adresse und UDP-Kommunikation

boost:asio IPv4-Adresse und UDP-Kommunikation


Problem gelöst – Lösungshinweise siehe unten


Ich versuche, eine einfache App zu erstellen, um einen Ethernet-fähigen Mikrocontroller zu testen. Ich möchte nur kleine UDP-Pakete senden und empfangen. Der Code verwendet boost::asio für das Netzwerk und ist unglaublich einfach. Zum Debuggen habe ich die gesamte Initialisierung aus den Konstruktoren verschoben, damit ich jeden Schritt überprüfen konnte. Hier ist der Inhalt meiner Sachen:


    boost::system::error_code myError;
boost::asio::ip::address_v4 targetIP;
targetIP.from_string("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<char, 128> 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);

Der Haken passiert gleich am Anfang. Die Adresse_v4 will die IP, die ich ihr übergebe, nicht akzeptieren. Die Ausgabe dieser App ist:


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

Ich gehe davon aus, dass der Sendefehler auf address_v4 zurückzuführen ist nicht richtig eingestellt, aber ich kann mir keinen Grund vorstellen, warum so etwas passieren sollte.


Für diejenigen, die zu Hause mitspielen, mein PC verfügt über zwei Ethernet-Karten, von denen eine mit DHCP 10.1.1.7 versehen wurde, sodass die Ziel-IP ohne Routing erreichbar sein sollte. Ich verwende BOOST 1.46.1 auf 32-Bit Win7 und MSVS 10. Es schlägt auch fehl, wenn ich eine IP von 127.0.0.1 versuche , korrigieren Sie mich, wenn ich falsch liege, aber das sollte in diesem Zusammenhang für Loopback funktionieren?


Mit Aktualisierungen bearbeiten:


Dank der früheren Antworten habe ich die IP-Adresse in meinen address_v4 bekommen , und ich versuche nicht mehr zu binden, wenn ich connect verwenden wollte. Der wesentlich geänderte Codeabschnitt ist der TX, der jetzt so aussieht:


    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;

(Ich habe myEndpoint in targetEndpoint umbenannt, um Verwirrung zu vermeiden.....)


Ich bekomme jetzt beim Senden den Fehler:

The attempted operation is not supported for the type of object referenced

Für eine aussagekräftige Fehlermeldung würde ich an dieser Stelle meinen Erstgeborenen geben! Der Fehler ist konsistent, unabhängig davon, welchen Zielport ich verwende. Das einzige, was mir einfällt, ist, dass ich den Quellport irgendwo einstellen muss, aber ich sehe nicht, wie Sie das in einem der boost::asio tun können Dokumentation.


Endgültige Auflösung


Ich habe es geschafft, dass dies funktioniert, also werde ich die Fallstricke, die ich gefunden habe, in einer netten, übersichtlichen Liste für alle anderen posten, die über diese Antwort mit ähnlichen Problemen wie ich stolpern. Ich denke, das Hauptproblem, das ich hatte, war, dass keines der Boost-Beispiele jemals zeigt, wie man eine Verbindung zu einer bestimmten IP herstellt, sie alle verwenden einen Resolver. Das hat die Beispiele für mich viel schwerer verständlich gemacht.



  • Bei Verwendung des from_string Aufruf zum Konvertieren einer Text-IP, verwenden Sie die Syntax aus der ersten Antwort unten und nicht meine Syntax oben!

  • Beim Einrichten des UDP-Sockets ist die Reihenfolge der Operationen entscheidend! Wenn Sie dies nicht im Konstruktor tun möchten, müssen Sie:



    1. Öffnen Sie den Socket mit dem erforderlichen Protokoll.

    2. Binden Sie den Socket an einen lokalen Endpunkt, der die Quelle angibt UDP-Portnummer.

    3. Verbinden Sie den Socket mit dem entfernten Endpunkt, der das Ziel angibt IP und Portnummer.


    Der Versuch, nach der Verbindung zu binden, führt dazu, dass die Bindung fehlschlägt. Die Übertragung funktioniert problemlos, aber Ihre Pakete werden von einer beliebigen Portnummer gesendet.


  • Verwenden Sie eine Sendemethode, um tatsächlich zu übertragen. Versuchen Sie nicht, Debugging-Daten mit boost::asio::socket_base::debug(true) zu aktivieren ! Alles, was dieses Flag zu tun scheint, ist, Fehlermeldungen innerhalb eines ansonsten funktionierenden Sends zu verursachen!


Ich möchte auch mitteilen, dass mein wertvollstes Debugging-Tool in dieser gesamten Übung Wireshark war. Vielleicht liegt es nur daran, dass ich es gewohnt bin, einen CRO oder Protokollanalysator zu haben, wenn ich an solchen Kommunikationen arbeite, aber ich fand, dass die Anzeige der Bytes-on-Wire mir dabei geholfen hat, eine ganze Menge Dinge zu sortieren, die ich habe wäre sonst nie aufgespürt worden.


Vielen Dank für Ihre Hilfe bei den IP-Problemen und die Hilfe, den Unterschied zwischen verbinden und binden zu erkennen.


Antworten:


Das Problem, das Sie derzeit sehen, scheint Ihre Verwendung dieser Zeile zu sein:


targetIP.from_string("10.1.1.75", myError); 

boost::asio::ip::address::from_string ist eine statische Funktion, die einen konstruierten ip::address zurückgibt Objekt. Ändern Sie es so, dass es so aussieht:


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

Und Ihre IP-Adresse sollte korrekt eingetragen sein.


Einige Code-Antworten


    boost::system::error_code myError;
boost::asio::ip::address_v4 targetIP;
targetIP.from_string("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<char, 128>
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);
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 
    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;
targetIP.from_string("10.1.1.75", myError);
targetIP = boost::asio::ip::address::from_string("10.1.1.75", myError);
targetIP = boost::asio::ip::address::from_string("10.1.1.75", myError);
targetIP = boost::asio::ip::address_v4::from_string("10.1.1.75", myError);