2017-05-30 4 views
1

Ich muss mit einem anderen Gerät in einem privaten Netzwerk über UDP kommunizieren. Ich bin neu in der Verwendung von Boost, aber basierend auf dem, was ich online suchte und auch den Tutorials auf der Boost-Website, kam ich unten Code .. Ich versuche derzeit, Daten von meinem eigenen Gerät zu senden und zu empfangen. Nur um den Test zu testen und den Code zu finalisieren.UDP-Kommunikation mit C++ Boost Asio

Frage: Ich kann keine Nachricht empfangen. Was vermisse ich?

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <string> 
#include "boost/asio.hpp" 
#include <thread> 
#include <boost/array.hpp> 
#include <boost/bind.hpp> 

#define SRVR_UDP_PORT 10251 
#define CLNT_UDP_PORT 10252 

boost::array<char, 1024> recv_buffer; 

void Sender(std::string in) 
{ 
    boost::asio::io_service io_service; 
    boost::asio::ip::udp::socket socket(io_service); 
    boost::asio::ip::udp::endpoint remote_endpoint; 
    socket.open(boost::asio::ip::udp::v4()); 
    remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("192.168.1.64"), SRVR_UDP_PORT); 

    boost::system::error_code err; 
    socket.send_to(boost::asio::buffer(in.c_str(), in.size()), remote_endpoint, 0, err); 
    socket.close(); 
    //int i =0; 
    printf("Sending Payload --- \n"); 
} 

void handle_receive(const boost::system::error_code& error, size_t bytes_transferred) 
{ 
    std::cout << "Received: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "'\n"; 
} 


void Receiver() 
{ 
    while(1) 
    { 
     boost::asio::io_service io_service; 
     boost::asio::ip::udp::socket socket(io_service); 
     boost::asio::ip::udp::endpoint remote_endpoint; 

     //socket.open(boost::asio::ip::udp::v4()); 
     boost::system::error_code err; 
     remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("192.168.1.64"), CLNT_UDP_PORT); 

     socket.open(boost::asio::ip::udp::v4()); 
     //https://stackoverflow.com/questions/26820215/boost-asio-udp-client-async-receive-from-calls-handler-even-when-there-are-no-in 
     socket.async_receive_from(boost::asio::buffer(recv_buffer), 
            remote_endpoint, 
            boost::bind(handle_receive, 
            boost::asio::placeholders::error, 
            boost::asio::placeholders::bytes_transferred));          
            //socket.close(); 
    } 
    int i = 0; 
    printf("Received Payload --- %d", i); 

} 

int main(int argc, char *argv[]) 
{ 
    //std::thread s(Sender); 
    std::thread r(Receiver); 
    //s.join(); 
    std::string input = argv[1]; 
    printf("Input is %s\nSending it to Sender Function...\n", input.c_str()); 
    Sender(input); 
    r.join(); 
    return 0; 
} 

Antwort

4

Sie vergessen den gleichen UDP-Port für den Empfänger zu

  1. binden die Aufnahmebuchse
  2. laufen die io_service

Es gibt keine async_* Anrufe tun Verwendung ist verwenden in eine Schleife, weil sie nur Aufgaben in der Warteschlange ausführt, die nur ausgeführt werden, wenn ein Thread ausgeführt wird io_service::run.

Live On Coliru

#include <boost/asio.hpp> 
#include <boost/array.hpp> 
#include <boost/bind.hpp> 
#include <thread> 
#include <iostream> 

#define IPADDRESS "127.0.0.1" // "192.168.1.64" 
#define UDP_PORT 13251 

using boost::asio::ip::udp; 
using boost::asio::ip::address; 

void Sender(std::string in) { 
    boost::asio::io_service io_service; 
    udp::socket socket(io_service); 
    udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT); 
    socket.open(udp::v4()); 

    boost::system::error_code err; 
    auto sent = socket.send_to(boost::asio::buffer(in), remote_endpoint, 0, err); 
    socket.close(); 
    std::cout << "Sent Payload --- " << sent << "\n"; 
} 

struct Client { 
    boost::asio::io_service io_service; 
    udp::socket socket{io_service}; 
    boost::array<char, 1024> recv_buffer; 
    udp::endpoint remote_endpoint; 

    int count = 3; 

    void handle_receive(const boost::system::error_code& error, size_t bytes_transferred) { 
     if (error) { 
      std::cout << "Receive failed: " << error.message() << "\n"; 
      return; 
     } 
     std::cout << "Received: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "' (" << error.message() << ")\n"; 

     if (--count > 0) { 
      std::cout << "Count: " << count << "\n"; 
      wait(); 
     } 
    } 

    void wait() { 
     socket.async_receive_from(boost::asio::buffer(recv_buffer), 
      remote_endpoint, 
      boost::bind(&Client::handle_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
    } 

    void Receiver() 
    { 
     socket.open(udp::v4()); 
     socket.bind(udp::endpoint(address::from_string(IPADDRESS), UDP_PORT)); 

     wait(); 

     std::cout << "Receiving\n"; 
     io_service.run(); 
     std::cout << "Receiver exit\n"; 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    Client client; 
    std::thread r([&] { client.Receiver(); }); 

    std::string input = argc>1? argv[1] : "hello world"; 
    std::cout << "Input is '" << input.c_str() << "'\nSending it to Sender Function...\n"; 

    for (int i = 0; i < 3; ++i) { 
     std::this_thread::sleep_for(std::chrono::milliseconds(200)); 
     Sender(input); 
    } 

    r.join(); 
} 

Drucke

Input is 'hello' 
Sending it to Sender Function... 
Receiving 
Sent Payload --- 5 
Received: 'hello' (Success) 
Count: 2 
Sent Payload --- 5 
Received: 'hello' (Success) 
Count: 1 
Sent Payload --- 5 
Received: 'hello' (Success) 
Receiver exit 
+0

** Anfänger Frage ** io_service.run(); Der Befehl wird nicht ausgeführt, da er auf die wait-Anweisung folgt. Es wird nur ausgeführt, bevor die Funktion beendet wird. Warum wird es überhaupt benötigt? – yath

+1

Ich erklärte es. So ist die Dokumentation: [am Ende] (http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/overview/core/basics.html) und z.B. der allererste asynchrone Lernschritt http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/tutorial/tuttimer2.html. Der Punkt ist, obwohl Sie die Funktion 'wait' _named_, überhaupt nicht _wait_. Denn das wäre nicht "asynchron" – sehe