2017-05-30 222 views
1

我需要通過UDP與專用網絡中的其他設備進行通信。我是使用boost的新手,但基於我在網上搜索的內容以及Boost網站上的教程,我想出了下面的代碼..我目前正嘗試從我自己的設備發送和接收數據。只是爲了單元測試並最終確定代碼。使用C++ boost asio的UDP通信

問題:我無法收到任何消息。我錯過了什麼?

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

回答

4

您忘記

  1. 綁定接收插座
  2. 運行io_service
  3. 使用相同的UDP端口接收

也沒有用在做async_*電話一個循環,因爲它所做的只是隊列任務,除非線程運行,否則這些任務將不會執行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(); 
} 

打印

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

**初級問題** io_service.run();命令沒有運行,因爲它在等待語句之後。它只在函數退出前執行。爲什麼甚至需要? – yath

+1

我解釋了它。文檔也是這樣:[底部](http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/overview/core/basics.html)和例如第一個異步教程步驟http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/tutorial/tuttimer2.html。關鍵是,即使你已經命名了函數「wait」,它根本就不會等待。因爲那不會是'異步' – sehe