Frage

Ich entwickle ein diagnostisches Tool auf einem PC mit mehreren Netzwerkschnittstellen basierend auf Multicast/UDP. Der Benutzer kann eine NIC auswählen, die Anwendung erstellt Sockets, bindet sie an diese NIC und fügt sie zur spezifischen Multicast -Gruppe hinzu.

Das Senden von Multicast -Nachrichten funktioniert einwandfrei. Das Empfangen von Nachrichten ist jedoch nur erfolgreich, wenn ich die Steckdosen an eine bestimmte NIC meines PC binden. Es sieht fast so aus, als ob es eine "Standard" -Nic für den Empfangen von Multicast -Nachrichten in Windows gibt, die immer die erste NIC - GetAdapterInfo Funktion.

Ich habe das Netzwerk mit Wireshark überwacht und festgestellt, dass die Nachricht "IGMP Join Group" nicht von der NIC gesendet wird.

Wenn ich diese NIC (oder das Netzwerkkabel entfernen) deaktiviere, wird die nächste NIC der von GetAdapterInfo zurückgegebenen Liste zum Empfangen von Multicast -Nachrichten verwendet.

Es war mir erfolgreich, diese "Standard" -Nic zu ändern, indem ich einen zusätzlichen Eintrag in die Routing -Tabelle meines PCs hinzufügte, aber ich denke nicht, dass dies eine gute Lösung des Problems ist.

Das Problem tritt auch mit dem unten angehängten Code auf. Die Join -Gruppenmeldungen werden nicht über 192.168.52 gesendet, sondern über eine andere NIC.

// socket_tst.cpp : Defines the entry point for the console application.
//

\#include tchar.h
\#include winsock2.h
\#include ws2ipdef.h
\#include IpHlpApi.h
\#include IpTypes.h

\#include stdio.h

int _tmain(int argc, _TCHAR* argv[])
{
  WSADATA       m_wsaData;
  SOCKET        m_socket;
  sockaddr_in   m_sockAdr;
  UINT16        m_port = 319;
  u_long        m_interfaceAdr = inet_addr("192.168.1.52");
  u_long        m_multicastAdr = inet_addr("224.0.0.107");

  int returnValue = WSAStartup(MAKEWORD(2,2), &m_wsaData);
  if (returnValue != S_OK)
  {
    return returnValue;
  }

  // Create sockets
  if (INVALID_SOCKET == (m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) )
  {
    return WSAGetLastError();
  }

  int doreuseaddress = TRUE;
  if (setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,(char*) &doreuseaddress,sizeof(doreuseaddress)) == SOCKET_ERROR)
  {
    return  WSAGetLastError(); 
  }

  // Configure socket addresses
  memset(&m_sockAdr,0,sizeof(m_sockAdr));
  m_sockAdr.sin_family =        AF_INET;
  m_sockAdr.sin_port =          htons(m_port);   
  m_sockAdr.sin_addr.s_addr =   m_interfaceAdr;

  //bind sockets
  if ( bind( m_socket, (SOCKADDR*) &m_sockAdr, sizeof(m_sockAdr) )  == SOCKET_ERROR )
  {
    return  WSAGetLastError();
  }

  // join multicast
  struct ip_mreq_source imr; 

  memset(&imr,0,sizeof(imr));
  imr.imr_multiaddr.s_addr  = m_multicastAdr; // address of multicastgroup
  imr.imr_sourceaddr.s_addr = 0;              // sourceaddress (not used)
  imr.imr_interface.s_addr  = m_interfaceAdr; // interface address
  /* first join multicast group, then registerer selected interface as 
  * multicast sending interface */
  if( setsockopt( m_socket 
                  ,IPPROTO_IP
                  ,IP_ADD_MEMBERSHIP
                  ,(char*) &imr
                  , sizeof(imr)) 
                  == SOCKET_ERROR)
  {
    return SOCKET_ERROR;
  }
  else
  {
    if( setsockopt(m_socket 
                  ,IPPROTO_IP
                  ,IP_MULTICAST_IF
                  ,(CHAR*)&imr.imr_interface.s_addr
                  ,sizeof(&imr.imr_interface.s_addr)) 
                  == SOCKET_ERROR )
    {
      return SOCKET_ERROR;
    }
  }

  printf("receiving msgs...\n");
  while(1)
  {
    // get inputbuffer from socket
    int sock_return = SOCKET_ERROR;
    sockaddr_in socketAddress;
    char buffer[1500];

    int addressLength = sizeof(socketAddress);
    sock_return = recvfrom(m_socket, (char*) &buffer, 1500, 0, (SOCKADDR*)&socketAddress, &addressLength );
    if( sock_return == SOCKET_ERROR)
    {
      int wsa_error = WSAGetLastError();
      return wsa_error;
    } 
    else
    {
      printf("got message!\n");
    }
  }

  return 0;
}

Danke vier deine Hilfe!

War es hilfreich?

Lösung

Das Problem war ein einfacher Tippfehler. Anstatt die Struktur zu verwenden struct ip_mreq_source, die Struktur struct ip_mreq muss verwendet werden, wenn die Option ip_multicast_if verwendet werden. (Die andere Struktur ist für die Option IP_ADD_Source_Membership erforderlich)

Die Verwendung der falschen Struktur hatte höchstwahrscheinlich das Ergebnis, dass die Setsockeopt -Funktion eine Null fand, bei der die NIC -IP -Adresse erwartet wurde. Null ist auch der Wert der InAddr_any -Konstante, die die Standard -NIC des Systems auswählt. :-)

Andere Tipps

Möglicherweise möchten Sie Ihre Routing -Tabelle überprüfen/ändern. Es gibt eine Route für Multicast (224.0.0.0, Subnetz 240.0.0.0) mit seiner entsprechenden Metrik:

C:\Users\Cetra>netstat -rn

*****

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0   192.168.80.254    192.168.80.99     20
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    306
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    306
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    306
     192.168.80.0    255.255.255.0         On-link     192.168.80.99    276
    192.168.80.99  255.255.255.255         On-link     192.168.80.99    276
   192.168.80.255  255.255.255.255         On-link     192.168.80.99    276

        224.0.0.0        240.0.0.0         On-link         127.0.0.1    306 
        224.0.0.0        240.0.0.0         On-link     192.168.80.99    276

  255.255.255.255  255.255.255.255         On-link         127.0.0.1    306
  255.255.255.255  255.255.255.255         On-link     192.168.80.99    276

******
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top