2016-12-15 23 views
0

我在線獲得了這個代碼,並且一直試圖向它添加一個計時器,以便它每隔一段時間就讀一個數據包。我似乎無法弄清楚如何通過一個回調函數來了boost :: async_wait命令,因爲我得到這個錯誤:如何將異步定時器添加到升級UDP服務器?

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類:

#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; 
} 

一個問題,我試圖用這個代碼回答是,如果我用一堆UDP數據包從客戶端發送服務器垃圾郵件,服務器會在async_wait期間忽略所有數據包嗎?

此外,我的主要目標是將此代碼放入我擁有的quadcopter代碼中。它是否會按照寫入的方式實例化這個類並讓它從地面站讀取數據包以獲取用戶輸入?

回答

2

使用bind和成員函數的方式是錯誤的。使用它如下所示:

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

至於爲什麼它是這樣的,我會建議你閱讀增強文檔。

另外,我修改了代碼,使其實際上像服務器一樣運行而不退出。爲此,我做了以下2個更改:

  1. 初始化io_service在main函數中並將其引用給類。
  2. 初始化io_service_work對象。這作爲io_service的常年工作來源。因此,io_service永遠不會從run函數返回,除非work對象被銷燬。

完整的源:

#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(); 
} 

注:即使它是一個服務器,這個類是名客戶。我忽略了:)

+0

哇,謝謝你的說明。我甚至沒有意識到那個哈哈。至於更新,我實際上可以編譯,所以謝謝。但是,我有一個新問題,那就是async_wait不會導致服務器等待2秒鐘。我用很多郵件發送垃圾郵件,並且收到每封郵件都沒有延遲。 – rangeme

+0

哦,好吧,我明白了。 async_wait會在2秒後取消定時器,因此您必須調用expires_from_now? – rangeme

+0

現在它正在工作,我測試瞭如果使用UDP數據包從客戶端向服務器發送服務器垃圾郵件,會發生什麼情況。即使我每2秒調用一次async_receive_from,它仍然會獲得每一個數據包。所以它落後了。是否可以忽略async_receive_from調用之間的所有數據包? – rangeme

相關問題