2016-12-15 6 views
0

Ich habe diesen Code online und habe versucht, einen Timer hinzuzufügen, so dass es ein Paket ab und zu liest. Ich kann nicht scheinen, um herauszufinden, wie man eine Callback-Funktion auf den boost :: async_wait Befehl übergeben, weil ich diese Störung erhalte:Wie kann ich einem Boost-UDP-Server einen asynchronen Timer hinzufügen?

server1.cpp: In member function ‘void UDPClient::handle_receive(const boost::system::error_code&, size_t)’: 
server1.cpp:51:66: error: invalid use of non-static member function ‘void UDPClient::time_to_receive(const boost::system::error_code&)’ 
            boost::asio::placeholders::error)); 
                   ^
server1.cpp:33:6: note: declared here 
void UDPClient::time_to_receive(const boost::system::error_code& error) 
     ^~~~~~~~~ 

UdpClient Klasse:

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

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

class UDPClient 
{ 
public: 
    boost::asio::io_service io_service; 
    udp::socket socket; 
    udp::endpoint receiver_endpoint; 
    boost::asio::deadline_timer timer; 
    boost::array<char, 1024> recv_buffer; 

    UDPClient(); 
    void time_to_receive(const boost::system::error_code& error); 
    void do_receive(); 
    void handle_receive(const boost::system::error_code& error, size_t); 
}; 

UDPClient::UDPClient() 
    : io_service(), 
     socket(io_service, {udp::v4(), 3643}), 
     timer(io_service, boost::posix_time::seconds(2)) 
{ 
    do_receive(); 
    io_service.run(); 
} 

void UDPClient::time_to_receive(const boost::system::error_code& error) 
{ 
    do_receive(); 
} 

void UDPClient::do_receive() 
{ 
    socket.async_receive_from(boost::asio::buffer(recv_buffer), receiver_endpoint, 
           boost::bind(&UDPClient::handle_receive, this, 
           boost::asio::placeholders::error, 
           boost::asio::placeholders::bytes_transferred)); 
} 

void UDPClient::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"; 

    timer.async_wait(boost::bind(time_to_receive, 
           boost::asio::placeholders::error)); 
} 

int main() 
{ 
    UDPClient updclient; 
} 

Eine Frage, die ich bin versuchen, mit diesem Code zu beantworten ist, wenn ich den Server von einem Client mit einer Reihe von UDP-Pakete spam den Server alle Pakete während der async_wait ignorieren?

Auch mein Hauptziel ist es, diesen Code in einen Quadcopter-Code, den ich habe, zu setzen. Funktioniert es so, wie es geschrieben wurde, um diese Klasse zu instanziieren und Pakete von einer Bodenstation lesen zu lassen, um Benutzereingaben zu erhalten?

Antwort

2

Die Art, wie Sie bind mit Elementfunktion verwenden, ist falsch. Verwenden Sie es wie unten dargestellt:

timer.async_wait(boost::bind(&UDPClient::time_to_receive, this, 
          boost::asio::placeholders::error)); 

Wie, warum es so ist, würde ich Ihnen empfehlen, die Boost-Dokumentation für das zu lesen.

Außerdem habe ich den Code so geändert, dass er wie ein Server läuft, ohne zu beenden. Dazu habe ich folgende 2 Änderungen vorgenommen:

  1. Initialisierung von io_service in Hauptfunktion und übergeben Sie ihren Verweis auf die Klasse.
  2. Initialisieren Sie ein Objekt io_service_work. Dies dient als eine ständige Quelle der Arbeit für die io_service. io_service kehrt also nie von der run-Funktion zurück, wenn das Objekt work nicht zerstört wird.

Die vollständige Quelle:

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

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

class UDPClient 
{ 
public: 
    boost::asio::io_service& io_service; 
    udp::socket socket; 
    udp::endpoint receiver_endpoint; 
    boost::asio::deadline_timer timer; 
    boost::array<char, 1024> recv_buffer; 

    UDPClient(boost::asio::io_service&); 
    void time_to_receive(const boost::system::error_code& error); 
    void do_receive(); 
    void handle_receive(const boost::system::error_code& error, size_t); 
}; 

UDPClient::UDPClient(boost::asio::io_service& ios) 
    : io_service(ios), 
     socket(io_service, {udp::v4(), 3643}), 
     timer(io_service, boost::posix_time::seconds(2)) 
{ 
    do_receive(); 
} 

void UDPClient::time_to_receive(const boost::system::error_code& error) 
{ 
    do_receive(); 
} 

void UDPClient::do_receive() 
{ 
    socket.async_receive_from(boost::asio::buffer(recv_buffer), receiver_endpoint, 
           boost::bind(&UDPClient::handle_receive, this, 
           boost::asio::placeholders::error, 
           boost::asio::placeholders::bytes_transferred)); 
} 

void UDPClient::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"; 
    timer.expires_from_now(boost::posix_time::seconds(2)); 
    timer.async_wait(boost::bind(&UDPClient::time_to_receive, this, 
           boost::asio::placeholders::error)); 
} 

int main() 
{ 
    boost::asio::io_service ios; 
    boost::asio::io_service::work wrk(ios); 
    UDPClient updclient(ios); 
    ios.run(); 
} 

HINWEIS: Auch wenn es ein Server ist, ist der Klassenname-Client. Ich ignoriere das :)

+0

Wow, danke für die Notiz. Das habe ich nicht einmal bemerkt, haha. Was die Updates angeht, kann ich das eigentlich kompilieren, danke. Ich habe jedoch ein neues Problem darin, dass der async_wait den Server nicht dazu bringt, 2 Sekunden zu warten. Ich spamme den Server mit vielen Nachrichten und er empfängt jede Nachricht ohne Verzögerung dazwischen empfängt. – rangeme

+0

Oh, ok ich verstehe. Der async_wait bricht den Timer nach 2 Sekunden ab, also müssen Sie expires_from_now aufrufen? – rangeme

+0

Jetzt, wo es funktioniert, habe ich getestet, was passiert, wenn ich den Server von einem Client mit UDP-Paketen spamme. Obwohl ich async_receive_from alle 2 Sekunden anrufe, bekommt es immer noch jedes einzelne Paket. Es ist also weit hinterherhinken. Ist es möglich, alle Pakete zwischen async_receive_from-Anrufen zu ignorieren? – rangeme

Verwandte Themen