c ++ - boost: Asio IPv4-adresse og UDP-komm

Indlæg af Hanne Mølgaard Plasc

Problem



Problemet løst - Se bunden til løsningsnotater


Jeg forsøger at opbygge en simpel app til at teste en ethernet-kompatibel mikrocontroller. Alt jeg vil gøre er at sende og modtage små UDP-pakker. Koden bruger boost :: asio til netværket og er utrolig simpelt. flyttede al intialisering ud af konstruktørerne, så jeg kunne tjekke hvert trin. Her er kropet af mine ting:


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


Hængen sker lige i begyndelsen. Adressen\_v4 ønsker ikke at acceptere den IP, som jeg går ind i den. Udgangen af ​​denne app er:


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


Jeg antager, at sendfejlen er et resultat af, at address\_v4 ikke bliver indstillet korrekt, men der er ingen grund til, at jeg kan tænke på, at sådan en ting skal finde sted.


For dem der følger med hjemme, har min pc dobbelt Ethernet-kort, hvoraf den ene har været DHCP 'd 10.1.1.7, så mål-IP'en skal kunne nås uden routing. Jeg bruger BOOST 1.46.1 på 32-bit Win7 og MSVS 10. Det svigter også, når jeg prøver en IP på 127.0.0.1, retter mig om jeg er forkert, men det burde fungere for loopback i denne sammenhæng?


Rediger med opdateringer:


Så takket være de tidligere svar har jeg fået IP-adressen til min address\_v4, og jeg forsøger ikke længere at binde, når jeg mente at bruge forbindelse. Den signifikant ændrede del af kode er TX, som nu ser ud som:


    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;


(Jeg omdøbte myEndpoint til targetEndpoint for at reducere forvirring .....)


Jeg får nu fejlen under forsøget at sende:

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

Jeg ville give min førstefødte en informativ fejlmeddelelse på dette tidspunkt! Fejlen er ens, uanset hvilken målport jeg bruger. Det eneste jeg kan tænke på er, at jeg skal sætte kildeporten et sted, men jeg kan ikke se, hvordan du kan gøre det i nogen af ​​boost::asio dokumentationen.


Endelig opløsning


Jeg har formået at gøre dette arbejde, så jeg kommer til at sende de gotkas, som jeg fandt i en flot, pæn liste for alle andre, der snuble over dette svar med lignende problemer for mig. Jeg tror, ​​at det vigtigste problem jeg havde, var at ingen af boost-eksemplerne viser nogensinde, hvordan man forbinder til en bestemt IP, de bruger alle en resolver. Det gjorde eksemplerne meget sværere at forstå for mig.



  • Når du bruger from\_string -opkaldet til at konvertere en tekst-IP, skal du bruge syntaksen fra det første svar nedenfor i stedet for min syntaks ovenfor!

  • Når du opretter UDP-stikket, er rækkefølge af operationer afgørende! Hvis du ikke vil gøre det i konstruktøren, skal du:



    1. Åbn stikket ved hjælp af den nødvendige protokol.

    2. Bind stikket til et lokalt endepunkt, der specificerer kilde UDP portnummer.

    3. Tilslut stikket til det eksterne endepunkt, der angiver destination IP- og portnummer.



    Forsøg på at binde efter forbindelsen vil medføre, at bindingen svigter. Overførslen fungerer fint, men dine pakker vil blive sendt fra et vilkårlig portnummer.

  • Brug en sendemetode til faktisk at transmittere. Forsøg ikke at aktivere fejlfindingsdata med boost::asio::socket\_base::debug(true)! Alt dette flag synes at gøre, er at forårsage fejlmeddelelser inden for en ellers funktionel sende!



Jeg vil også gerne dele, at mit mest værdifulde fejlfindingsværktøj i hele denne øvelse var Wireshark. Måske er det kun fordi jeg har brugt en CRO- eller protokolanalysator, når jeg arbejder på kommandoer som dette, men jeg fandt At kunne se bytes-on-wire-displayet hjalp mig med at sortere en hel spand af ting, som jeg ellers aldrig ville have sporet.


Skål for din hjælp på IP-problemerne og hjælpe mig med at indse forskellen mellem forbindelse og bind.

Bedste reference


Det problem, du ser i øjeblikket, synes at være din brug af denne linje:


targetIP.from\_string("10.1.1.75", myError); 


boost::asio::ip::address::from\_string er en statisk funktion, der returnerer en konstrueret ip::address objekt. Skift det for at se sådan ud:


targetIP = boost::asio::ip::address::from\_string("10.1.1.75", myError); 


Og din IP-adresse skal være befolket korrekt.

Andre referencer 1


På toppen af ​​mit hoved forsøger du at binde stikket til et slutpunkt med adresse 10.1.1.75, men det synes at være et fjernt endepunkt? Jeg ville antage, at du gerne vil binde det lokalt og bruge send\_to, som det er UDP

Andre referencer 2


I denne linje er der en fejl:


targetIP = boost::asio::ip::address::from\_string("10.1.1.75", myError);


Du bør sætte:


targetIP = boost::asio::ip::address\_v4::from\_string("10.1.1.75", myError);


og derefter har targetIP den rigtige værdi!