2015-03-09 2 views
1

У меня есть хост с двумя интерфейсами. В моем конкретном случае я пытаюсь присоединиться к группе многоадресной рассылки, используя boost::asio::ip::multicast::join_group, которая, похоже, работает только в том случае, если я использую конструктор, содержащий локальный адрес. Однако я заранее не знаю IP-адрес локального интерфейса, подключенного к удаленному хосту, который будет выполнять многоадресную рассылку. Однако я знаю, что это будет eth1. Конечно, я могу настроить его, но это похоже на введение бесполезной возможности для неправильной настройки, видя, как один и тот же адрес должен быть настроен для интерфейса и моего приложения.Привязать сокет к определенному интерфейсу с неизвестным Ip

В идеале был бы явный способ создания boost::asio::endpoint или boost::asio::address из интерфейса вместо адреса, который я как-то пропустил. В качестве альтернативы я, конечно, был бы так же доволен любым другим способом вывода интерфейсов Ip, которые работают как с DHCP-сервером, так и без него, обеспечивающим Ip.

Есть ли способ сделать то или другое, или я просто доверяю пользователям, чтобы никогда не перепутаться с конфигурацией?

Чтобы убедиться, что это не совсем 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 

Это работает, но когда я отбросить последнюю строку, чтобы не быть в зависимости от текущего локального адреса (который может быть изменен при развертывании), я больше не получаю никаких пакетов.

ответ

1

Multicast использует протокол IGMP для формирования группы многоадресной передачи. Поскольку IGMP работает на сетевом уровне, для этого требуется локальный IP-адрес конечной точки, соединяющий группу многоадресной передачи.

Приложение должно дождаться события, указывающего, что IP-адрес был присвоен интерфейсу ethernet, а затем вызвать метод join_group для присоединения к группе многоадресной передачи.

+0

Я могу с уверенностью предположить, что Ip больше не будет изменен после запуска приложения. Но что было бы хорошим способом найти интерфейсы текущего Ip, если я не знаю, используется ли DHCP или нет? – DeVadder

+0

Здесь обсуждается получение IP-адреса программно: [link] (http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux) – Vivek

1

Я сам ответил на свой вопрос. Это работает для меня, но я оставлю вопрос открытым, если у кого-то будет более простое решение.

Я установил с использованием <ifaddrs.h>, чтобы просто найти мой текущий 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 непосредственно, но оказывается, что этот код может быть использован в одном другом месте, хорошо таким образом.

Смежные вопросы