2016-03-23 12 views
0

Ich habe eine Anwendung für Windows und OSX geschrieben, die Boost ASIO für das Networking verwendet. Ein Teil dieser Anwendung sendet eine Multicast-Nachricht für eingebettete Geräte, um darauf zu reagieren:Boost ASIO Multicast Fehler unter OSX

std::string ip_addr = "224.0.0.177"; 
boost::asio::ip::udp::endpoint senderEndpoint(boost::asio::ip::address::from_string(ip_addr), 7076); 
m_pcDiscoverySocket->send_to(boost::asio::buffer((void*)pGetDeviceInfoMessage->m_pchData, pGetDeviceInfoMessage->m_ulDataSize), senderEndpoint); 

Dieser Code funktioniert unter Windows absolut einwandfrei. Es funktioniert auch unter OSX, aber nur, wenn ein DHCP-Server im Netzwerk vorhanden ist. Wenn kein DHCP-Server im Netzwerk vorhanden ist und alle Adressen mit automatischer IP-Adresse 169.254.x.x zugewiesen sind, löst die Funktion send_to eine Ausnahme mit der Fehlermeldung "send_to: Network is unreachable" aus. Wenn ich die IP-Adresse in dem obigen Code zu 169.254.0.1 ändere, wird es ohne Fehlermeldungen ausgeführt, aber die eingebetteten Geräte reagieren offensichtlich nicht, da es keine Broadcast-IP-Adresse ist.

Ich bin ein bisschen verblüfft. Kann jemand erklären, warum es diesen Fehler gibt, oder warum der gleiche Code in Windows funktioniert (läuft in einer VM auf dem Mac mit identischer Hardware)?

Antwort

0

So nach vielen vergeblichen Suchens und ein paar Experimente Ich glaube, ich habe eine Lösung gefunden, die in der Frage die letzte Zeile des Codes beinhaltet Wechsel zu:

boost::asio::ip::tcp::resolver resolver(m_IOservice); 
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(),""); 
boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query); 
boost::asio::ip::address interface_ip_address; 

while(it!=boost::asio::ip::tcp::resolver::iterator()) 
{ 
    interface_ip_address = (it++)->endpoint().address(); 
    if(interface_ip_address.is_v4()) 
    { 
     m_pcDiscoverySocket->set_option(boost::asio::ip::multicast::outbound_interface(interface_ip_address.to_v4())); 
     m_pcDiscoverySocket->send_to(boost::asio::buffer((void*)pGetDeviceInfoMessage->m_pchData, pGetDeviceInfoMessage->m_ulDataSize), senderEndpoint); 
     break; 
    } 
} 

Grundsätzlich scheint es, dass auf OSX müssen Sie dem Socket mitteilen, welches Interface verwendet werden soll, aber nur, wenn es seine IP-Adresse nicht über DHCP bekommt. Dies scheint auch unter Windows zu funktionieren (obwohl es früher auch war).

Wenn jemand klüger als ich erklären kann, warum das funktioniert und warum Sie dies auf OSX tun müssen, dann werde ich ihnen die Anerkennung für die Antwort geben.

+0

Die Standardroute unter OSX (und Linux) wird basierend auf dem Schnittstellenstatus eingerichtet. Bei DHCP ist normalerweise die Standardschnittstelle richtig eingestellt, ohne DHCP ist die Standardschnittstelle wahrscheinlich nicht festgelegt oder nicht auf die Weiterleitung des Multicastverkehrs eingestellt. Mit mehreren Adaptern wird es noch schlimmer. – Chad