【问题标题】:Bind a socket to a specific interface with unknown Ip将套接字绑定到具有未知 Ip 的特定接口
【发布时间】:2015-05-10 20:39:45
【问题描述】:

我有一个有两个接口的主机。在我的具体情况下,我正在尝试使用 boost::asio::ip::multicast::join_group 加入多播组,这似乎只有在我使用包含本地地址的构造函数时才有效。但是,我事先不知道连接到将进行多播的远程主机的本地接口的 IP 地址。但是我知道它将是 eth1。当然,我可以使其可配置,但这似乎引入了一个无用的错误配置机会,看看如何为接口和我的应用程序配置相同的地址。

理想情况下,应该有一种非常明显的方法可以从接口创建boost::asio::endpointboost::asio::address,而不是我以某种方式错过的地址。或者,我当然会对任何其他方式来推断接口 Ip 感到满意,无论是否有提供 Ip 的 DHCP 服务器。

是否有适当的方法可以做到这一点,或者我应该相信用户永远不会摸索配置?

为了确保这不完全是 XY 问题,这是我在测试加入多播组时使用的代码:

m_socket.open(boost_ip::udp::v4());
m_socket.bind(boost_ip::udp::endpoint(boost_ip::udp::v4(), listeningPort));

m_socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));
m_socket.set_option(boost::asio::ip::multicast::join_group(
                  boost::asio::ip::address::from_string("225.x.x.10").to_v4(),  // remote
                  boost::asio::ip::address::from_string("192.x.x.3").to_v4())); // local

这确实有效,但是当我丢弃最后一行以不依赖于当前本地地址(可能在部署中更改)时,我不再收到任何数据包。

【问题讨论】:

    标签: c++ sockets centos boost-asio network-interface


    【解决方案1】:

    我自己想出了一个问题的答案。这对我有用,但如果有人有更直接的解决方案,我会留下这个问题。

    我选择使用<ifaddrs.h> 来找到我当前的接口 IP 并使用它来加入多播组。这是我最终确定我的 ip 的代码:

    #include <ifaddrs.h>
    #include <boost/asio.hpp>
    #include <cstring>
    
    std::string getInterfaceAddress(const std::string & interfaceName)
    {
        ifaddrs* firstNetIf = 0;
        getifaddrs(&firstNetIf);
    
        ifaddrs* netIf = 0;
        for(netIf = firstNetIf; netIf != 0; netIf = netIf->ifa_next)
        {
            if(netIf->ifa_addr->sa_family == AF_INET && std::strncmp(netIf->ifa_name, interfaceName.c_str(), interfaceName.length()) == 0)
            {
                break;
            }
        }
    
        unsigned long address =
                netIf != 0 ? reinterpret_cast<sockaddr_in*>(netIf->ifa_addr)->sin_addr.s_addr : 0;
    
        if(firstNetIf != 0)
        {
            freeifaddrs(firstNetIf);
        }
    
        return boost::asio::ip::address_v4(htonl(address)).to_string();
    }
    

    当然,就我而言,我可以与"eth1" 进行比较并直接返回boost::asio::ip::address,但事实证明,此代码也可以通过这种方式在其他地方使用。

    【讨论】:

      【解决方案2】:

      Multicast 使用 IGMP 协议来形成一个多播组。由于 IGMP 在网络层运行,它需要加入多播组的端点的本地 IP 地址。

      应用程序应等待一个事件表明 IP 地址已分配给以太网接口,然后调用 join_group 方法加入多播组。

      【讨论】:

      • 我可以放心地假设应用程序启动后 Ip 将不再更改。但是,如果我不知道是否使用了 DHCP,那么找到当前 Ip 接口的好方法是什么?
      • 这里有一个关于以编程方式获取IP地址的讨论:link
      猜你喜欢
      • 2016-10-23
      • 2012-05-26
      • 1970-01-01
      • 2017-03-11
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-12
      相关资源
      最近更新 更多