2011-12-21 13 views
5

Ho pensato di aver trovato la risposta nell'esempio seguente, ma non del tutto.Boost socket multicast su un'interfaccia ethernet specifica

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); 

Come posso mappare eth0 all'opzione outbound_interface appropriata?

+0

potrebbe desiderare di controllare la formattazione sul tuo post lì ... –

risposta

0

Il seguente codice funziona bene su Windows e 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: Ho avuto alcuni problemi su Linux, ma non ho guardato in esso ancora. La mia ipotesi è che l'opzione socket sia ignorata a favore della tabella di routing.

+5

quali sono '_read',' _write', '_descriptor' ecc.? – 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

Sarebbe molto meglio rispondere se includessi una breve spiegazione oltre al codice. In questo modo non solo risolve il problema ma mostra anche loro come farlo e anche perché. In questo modo impariamo tutti. – Simon

Problemi correlati