【问题标题】:Boost asio socket multicast to a specific ethernet interface将 asio 套接字多播提升到特定的以太网接口
【发布时间】:2012-01-25 12:04:49
【问题描述】:

我以为我在下面的例子中找到了答案,但不完全是。

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

如何将eth0 映射到适当的 outbound_interface 选项?

【问题讨论】:

  • 可能想检查您帖子的格式...

标签: boost interface boost-asio multicast


【解决方案1】:

以下代码在 Windows 和 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()));

编辑:我在 Linux 上遇到了一些问题,但还没有调查。我的猜测是套接字选项被忽略以支持路由表。

【讨论】:

    【解决方案2】:

    我认为您的示例和 eile 的示例不起作用的原因是因为您没有设置 SO_BINDTODEVICE 套接字选项。

    看看这个就知道为什么它不起作用了:http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html

    查看此内容以了解如何使用 boost::asio: http://permalink.gmane.org/gmane.comp.lib.boost.asio.user/2724

    【讨论】:

    • 链接现在被破坏了,这使得这个答案几乎没用。
    【解决方案3】:
    /**************************************************************************//**
    \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
    

    【讨论】:

    • 如果您包含简短的解释和代码,那将是更好的答案。这样,它不仅解决了问题,而且还向他们展示了如何做到这一点以及为什么这样做。这样我们都可以学习。
    【解决方案4】:

    http://permalink.gmane.org/gmane.comp.lib.boost.asio.user/2724 无效。 以下代码似乎无效:

    boost::asio::ip::address_v4 local_interface = 
    boost::asio::ip::address_v4::from_string(ip);
    boost::asio::ip::multicast::outbound_interface option(local_interface);
    sock.set_option(option);
    

    【讨论】:

    • 如何通过特定接口发送数据??提升 Asio。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 2017-02-16
    相关资源
    最近更新 更多