2016-01-11 8 views
2

Во-первых, я знаю, что здесь много вопросов, связанных с темами многоадресной рассылки. Я также видел, что проблема большинства людей не позволяет IP_MULTICAST_LOOP. Я уже получил это, и все еще получаю ошибку «Нет устройства».IP_ADD_MEMBERSHIP приводит к тому, что «никаких устройств не найдено», несмотря на IP_MULTICAST_LOOP (Linux, C++, UDP)

Я пишу программу, которая работает с интерфейсом loopback или с подключенными сетевыми устройствами, в зависимости от того, что пользователь делает аппаратно (подключайте или выходите из кабеля). Я использую UDP для передачи данных. Я на Linux и код на C++.

Когда сетевой кабель подключен и, скажем, eth0 работает, все в порядке (моя настройка многоадресной рассылки работает красиво). Если только lo доступен (и запущен, в соответствии с ifconfig), вызов

setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq))

терпит неудачу с -1, в результате чего errno не отчетности «Нет устройства найден».

Вот соответствующий кусок кода из моего MulticastEndpoint класса:

MulticastEndpoint::MulticastEndpoint(std::string strMulticastGroup, unsigned short usPort) : m_strMulticastGroup(strMulticastGroup), m_usPort(usPort) { 
    this->setSocket(::socket(AF_INET, SOCK_DGRAM, 0)); 

    memset(&m_saAddrGroup, 0, sizeof(m_saAddrGroup)); 
    m_saAddrGroup.sin_family = AF_INET; 
    m_saAddrGroup.sin_addr.s_addr = inet_addr(m_strMulticastGroup.c_str()); 
    m_saAddrGroup.sin_port = htons(m_usPort); 

    unsigned int unYes = 1; 
    bool bOK = false; 

    if(setsockopt(this->socket(), SOL_SOCKET, SO_REUSEADDR, &unYes, sizeof(unYes)) >= 0) { 
    if(setsockopt(this->socket(), IPPROTO_IP, IP_MULTICAST_LOOP, &unYes, sizeof(unYes)) >= 0) { 
     memset(&m_saAddrAny, 0, sizeof(m_saAddrAny)); 
     m_saAddrAny.sin_family = AF_INET; 
     m_saAddrAny.sin_addr.s_addr = htonl(INADDR_ANY); 
     m_saAddrAny.sin_port = htons(m_usPort); 

     if(bind(this->socket(), (struct sockaddr*)&m_saAddrAny, sizeof(m_saAddrAny)) >= 0) { 
     struct ip_mreq ipmReq; 
     ipmReq.imr_multiaddr.s_addr = inet_addr(m_strMulticastGroup.c_str()); 
     ipmReq.imr_interface.s_addr = htonl(INADDR_ANY); 

     if(setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq)) >= 0) { 
      bOK = true; 
     } 
     } 
    } 
    } 

    if(!bOK) { 
    std::cerr << strerror(errno) << std::endl; 
    ::close(this->socket()); 
    this->setSocket(-1); 
    } 

    std::cout << this->socket() << std::endl; 
} 

Класс создается с групповым адресом 224.0.0.1 и порт 2077. Методы setSocket(int) и socket() представляют собой простые функции сеттера и геттера, хранящие сокет как int в экземпляре.

У кого-нибудь есть ключ к этому поводу? Теоретически, многоадресная рассылка должна работать только с lo, не так ли? Кроме того, может быть, многоадресный адрес общего назначения, который я использую неправильно? И насколько мне известно о сокетах linux, INADDR_ANY должен также охватывать интерфейс loopback. Пожалуйста, поправьте меня, если это неправильно в этих обстоятельствах.

Я очень благодарен за любое просвещение.

ответ

0

Интерфейс loopback обычно не поддерживает многоадресную рассылку.

При запуске ifconfig -a когда у вас есть eth0 и работает, вы увидите, что eth0 имеет флаг для MULTICAST, а lo нет.

Вот что одна из моих машин дисплеях:

eth0  Link encap:Ethernet HWaddr 00:11:22:33:44:55 
      inet addr:10.112.161.84 Bcast:10.112.161.127 Mask:255.255.255.192 
      inet6 addr: fe80::211:22ff:fe33:4455/64 Scope:Link 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 
      RX packets:20001770 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:10074436 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:4589702477 (4.2 GiB) TX bytes:2896096295 (2.6 GiB) 

lo  Link encap:Local Loopback 
      inet addr:127.0.0.1 Mask:255.0.0.0 
      inet6 addr: ::1/128 Scope:Host 
      UP LOOPBACK RUNNING MTU:16436 Metric:1 
      RX packets:1212663 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:1212663 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:0 
      RX bytes:60939041 (58.1 MiB) TX bytes:60939041 (58.1 MiB) 

EDIT:

Для того, чтобы это работало, необходимо вручную включить многоадресного на шлейфом:

sudo ifconfig lo multicast 

После вы это сделаете, вы должны присоединиться к группе многоадресной передачи в loopback, однако вам нужно указать 127.0.0.1 вместо INADDR_ANY для ipmReq.imr_interface.