2011-12-21 27 views
5

Tôi nghĩ tôi đã tìm thấy câu trả lời trong ví dụ sau, nhưng không hoàn toàn.Tăng cổng đa cực asio lên một giao diện ethernet cụ thể

boost::asio::ip::udp::socket socket(io_service); 
... 
boost::asio::ip::address_v4 local_interface = 
    boost::asio::ip::address_v4::from_string("1.2.3.4"); 
boost::asio::ip::multicast::outbound_interface option(local_interface); 
socket.set_option(option); 

Làm cách nào để ánh xạ eth0 vào tùy chọn outbound_interface thích hợp?

+0

Có thể muốn kiểm tra định dạng trên bài viết của bạn có ... –

Trả lời

0

Các mã sau hoạt động tốt trên Windows và Mac OS X:

const ip::udp::resolver::query queryIF(ip::udp::v4(),     
             _description->getInterface(), "0"); 
    const ip::udp::resolver::iterator interfaceIP =       
     resolver.resolve(queryIF);           

    if(interfaceIP == end)             
     return false;               

    const ip::address ifAddr(ip::udp::endpoint(*interfaceIP).address()); 

    _read->set_option(ip::multicast::join_group(mcAddr.to_v4(),    
                ifAddr.to_v4()));   
    _write->set_option(ip::multicast::outbound_interface(ifAddr.to_v4())); 

EDIT: Tôi đã có một số vấn đề trên Linux, nhưng không nhìn vào nó được nêu ra. Đoán của tôi là tùy chọn socket được bỏ qua trong lợi của bảng định tuyến.

+5

'_read',' _write', '_descriptor', v.v. là gì? – example

0
/**************************************************************************//** 
\brief  
\details  
*******************************************************************************/ 
class UDPClient : public BoostSocketClient 
{ 
public: 
    UDPClient(); 
    virtual ~UDPClient(); 
    virtual ARLErrorCode_e open(int port_num, const char* network_type="ipv4", const char* ip_address="", uint32_t listen_interface=0); 
    virtual ARLErrorCode_e send(u8* message, u32 size); 
    virtual ARLErrorCode_e close(); 
    virtual bool isOpen(); 
    //virtual void onReceived(u8*, u32); 

private: 
    void startReceive(); 
    void handleReceive(const boost::system::error_code&, std::size_t); 
    void handleSend(const boost::system::error_code& error, std::size_t bytes_transferred); 

private: 
    boost::asio::io_service send_ios_; 
    std::unique_ptr<boost::asio::io_service::work> send_worker_; 

    boost::asio::io_service receive_ios_; 
    std::unique_ptr<boost::asio::io_service::work> receive_worker_; 

    boost::thread send_thread_; 
    boost::thread receive_thread_; 
    boost::array<u8, 1024> _buffer; 
    boost::asio::ip::udp::endpoint send_endpoint_; 
    boost::asio::ip::udp::endpoint sender_endpoint_; 
    boost::asio::ip::udp::endpoint listen_endpoint_; 

    std::unique_ptr<boost::asio::ip::udp::socket> send_udp_socket_; 
    std::unique_ptr<boost::asio::ip::udp::socket> receive_udp_socket_; 

}; 


#include <ACCompLib/Include/Typedefs.h> 
#include <ACCompLib/Include/ARLErrorCodes.h> 
#include <NetLib/Platform/Boost/cpp/UDPClient.h> 
#include "Ws2tcpip.h" 
#include "Iphlpapi.h" 


using namespace std; 
using namespace boost; 
using namespace asio; 
using namespace ip; 
using namespace NetLib; 

/***************************************************************************//** 
\brief   Constructor 
\details   

*******************************************************************************/ 
UDPClient::UDPClient() 
{ 
    receive_worker_.reset(new boost::asio::io_service::work(receive_ios_)); 
} 
/***************************************************************************//** 
\brief   ctor 
\details   
*******************************************************************************/ 
UDPClient::~UDPClient() 
{ 
    try 
    { 
     receive_worker_.reset(); 
     //send_worker_.reset(); 
     if (send_thread_.joinable()) { 
      send_thread_.join(); 
     } 
     if (receive_thread_.joinable()) { 
      receive_thread_.join(); 
     } 
    } 
    catch (std::exception& e) 
    { 
     std::string str = e.what(); 
    } 
} 

/***************************************************************************//** 
\brief   
\details   
\note   
\param[in]  
*******************************************************************************/ 
ARLErrorCode_e UDPClient::open(int port_num, const char* network_type, const char* multicastAddress, uint32_t listen_interface) 
{ 
    try 
    { 
     struct in_addr in; 
     in.S_un.S_addr = listen_interface; 
     char* address_listen = inet_ntoa(in); 
     //const char* address_listen = "0.0.0.0"; 
     std::string address_mcast = multicastAddress; 
     unsigned short address_port = port_num; 

     boost::system::error_code ec; 

     boost::asio::ip::address listen_addr = boost::asio::ip::address::from_string(address_listen, ec); 
     boost::asio::ip::address mcast_addr = boost::asio::ip::address::from_string(address_mcast, ec); 


     if (strcmp(network_type, "ipv4") == 0) 
     { 
      listen_endpoint_ = udp::endpoint(listen_addr, port_num); 
      send_endpoint_ = udp::endpoint(mcast_addr, port_num); 
     } 
     else if (strcmp(network_type, "ipv6") == 0) 
     { 
     } 
     else 
      return ES35_INVALID_SOCKET_CONNECTION; 

     send_udp_socket_.reset(new boost::asio::ip::udp::socket(send_ios_)); 
     receive_udp_socket_.reset(new boost::asio::ip::udp::socket(receive_ios_)); 

     send_udp_socket_->open(boost::asio::ip::udp::v4()); 
     receive_udp_socket_->open(listen_endpoint_.protocol()); 
     send_udp_socket_->set_option(boost::asio::ip::udp::socket::reuse_address(true)); 
     receive_udp_socket_->set_option(boost::asio::ip::udp::socket::reuse_address(true)); 

     boost::asio::ip::address_v4 local_interface = 
      boost::asio::ip::address_v4::from_string(address_listen); 
     boost::asio::ip::multicast::outbound_interface option(local_interface); 


     // Join the multicast group. 
     receive_udp_socket_->set_option(
      boost::asio::ip::multicast::join_group(mcast_addr)); 

     send_udp_socket_->set_option(option); 
     receive_udp_socket_->set_option(option); 

     boost::asio::ip::multicast::hops hops_option(3); 
     //send_udp_socket_->set_option(hops_option); 
     receive_udp_socket_->set_option(hops_option); 

     receive_udp_socket_->bind(listen_endpoint_); 


     startReceive(); 
     receive_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &receive_ios_)); 
     send_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &send_ios_)); 


     return ES_NoError; 
    } 
    catch (std::exception& exp) 
    { 
     std::string str = exp.what(); 
     return ES35_INVALID_SOCKET_CONNECTION; 
    } 
} 

/***************************************************************************//** 
\brief   
\details   
*******************************************************************************/ 
ARLErrorCode_e UDPClient::close(void) 
{ 
    try { 
     boost::system::error_code ec; 
     //udp_socket_->cancel(); 
     //udp_socket_.shutdown(socket_base::shutdown_both, ec); 
     if (ec) 
     { 
      return ES35_INVALID_SOCKET_CONNECTION; 
     } 
     if (send_udp_socket_->is_open()) 
     { 
      send_udp_socket_->close(); 
     } 
     if (receive_udp_socket_->is_open()) 
     { 
      receive_udp_socket_->close(); 
     } 

     receive_udp_socket_.reset(); 
     send_udp_socket_.reset(); 

    } 
    catch (std::exception& e) 
    { 
     std::string str = e.what(); 
     return ES35_INVALID_SOCKET_CONNECTION; 
    } 

    return ES_NoError; 
} 

/***************************************************************************//** 
\brief   
\details   
*******************************************************************************/ 
bool UDPClient::isOpen() 
{ 
    return send_udp_socket_->is_open() && receive_udp_socket_->is_open(); 
} 

/***************************************************************************//** 
\brief  Send a message.  
\details The message is sent asynchronously. 
\param  message 
\param  message size 
*******************************************************************************/ 
ARLErrorCode_e UDPClient::send(u8* message, u32 size) 
{ 
    if (!isOpen()) { 
     return ES35_INVALID_SOCKET_CONNECTION; 
    } 

    std::string send_to_address = send_endpoint_.address().to_string(); 



    send_udp_socket_->set_option(asio::ip::multicast::enable_loopback(false)); 

    send_udp_socket_->async_send_to(
     buffer(message, size), 
     send_endpoint_, 
     bind(
      &UDPClient::handleSend, 
      this, 
      asio::placeholders::error, 
      asio::placeholders::bytes_transferred)); 


    return ES_NoError; 
} 

/***************************************************************************//** 
\brief  Do nothing.   
\details This function has the required signature to be used as an 
      asynchronous send completion handler. 
\param  not used 
\param  not used 
*******************************************************************************/ 
void UDPClient::handleSend(const system::error_code& error, size_t) 
{ 
    if (error) 
    { 
     BoostSocketClient::onError(ES35_UDP_SEND_ERROR, (u8*)error.message().c_str(), error.message().size()); 
    } 
    else 
    { 
     send_udp_socket_->set_option(asio::ip::multicast::enable_loopback(true)); 
    } 
} 
/***************************************************************************//** 
\brief Start an asynchronous receiver.   
*******************************************************************************/ 
void NetLib::UDPClient::startReceive() 
{ 

    receive_udp_socket_->async_receive_from(
     buffer(_buffer), 
     sender_endpoint_, 
     bind(
      &UDPClient::handleReceive, 
      this, 
      asio::placeholders::error, 
      asio::placeholders::bytes_transferred)); 

    std::string sender_address = sender_endpoint_.address().to_string(); 
} 

/***************************************************************************//** 
\brief  Pass received data to the base class. 
\details A new receiver is started. 
\param  error code 
\param  data size 
*******************************************************************************/ 
void NetLib::UDPClient::handleReceive(const system::error_code& error, size_t size) 
{ 
    if (!error || error == error::message_size) 
    { 
     BoostSocketClient::onReceived(_buffer.data(), size); 

     startReceive(); 
    } 
    else   
    { 
     BoostSocketClient::onError(ES35_UDP_RECEIVE_ERROR, (u8*)error.message().c_str(), error.message().size()); 
    } 
} 


This code is not receiving response.please check 
+1

Nó sẽ là câu trả lời tốt hơn nhiều nếu bạn bao gồm một lời giải thích ngắn cũng như mã. Bằng cách đó, nó không chỉ giải quyết vấn đề mà còn cho họ thấy cách làm và cũng là lý do tại sao. Bằng cách đó, tất cả chúng ta đều học hỏi. – Simon

Các vấn đề liên quan