Mehrere Anwendungen verwenden dieselbe Multicast-Gruppe auf demselben Windows-Host

Mehrere Anwendungen verwenden dieselbe Multicast-Gruppe auf demselben Windows-Host

Ich bin Softwareentwickler und entwerfe eine verteilte Software, bei der der Startvorgang IP-Multicasting verwendet, um seine Gegenstücke zu finden. Die Software selbst wird in Form verschiedener ausführbarer Module verteilt, und daher ist es manchmal sinnvoll, mehrere ausführbare Module auf demselben Host auszuführen. Hier beginnen meine Probleme, da es mir so vorkommt, als sei Windows nicht gut darin, mehrere Prozesse zu verwalten, die eine einzige Multicast-Gruppe abonnieren.

Mein Ziel besteht darin, frei wählen zu können, auf welchen Hosts ich welche ausführbaren Dateien starte, und diese alle ihre Peers (sei es auf demselben Host oder auf anderen Hosts) ohne vordefiniertes Wissen erkennen zu können.

Die bisherige Fehlerbehebung deutet darauf hin, dass das Problem darin besteht, wie Windows mit dem Szenario umgeht, dass mehrere Prozesse dieselben Multicast-Gruppen abonnieren, weil:

  1. Wenn derselbe Prozess zum Senden und Empfangen von Multicast-Datagrammen auf derselben Maschine verwendet wird, funktioniert er wie erwartet. Der Prozess kann problemlos in mehrere Threads aufgeteilt werden.

  2. Wenn ich zum Senden und Empfangen unterschiedliche Prozesse ausführe, empfängt der empfangende Prozess nichts, obwohl die Gruppenbeitrittsnachricht und alle Datagramme in Wireshark angezeigt werden.

  3. Das in 2 beschriebene Szenario funktioniert, wenn ich vor dem Abhören denselben Socket auch verwende, um ein Paket an die Multicast-Gruppe zu senden, der ich beigetreten bin. Letztere empfängt dann für eine unbestimmte Zeit Multicast-Datagramme und hört dann lediglich auf, Datagramme zu empfangen (sie wartet weiter auf Datagramme). Das Senden der Datagramme an/vom Netzwerk wird mit Wireshark bestätigt.

  4. Meine neuesten Erkenntnisse zeigen, dass ich, wenn ich regelmäßig eine Multicast-Nachricht an die Gruppe sende, bei der ich angemeldet bin, Datagramme empfange, die an diese Multicast-Gruppe gesendet werden, auch von anderen Prozessen auf demselben Host.

IP-Multicast definiert meines Wissens nach nur die Kommunikation zwischenGastgeber, während es in der Verantwortung des Betriebssystems liegt, eingehende Pakete an die entsprechendenAnwendung. Da Pakete scheinbar immer in Wireshark angezeigt werden, auch wenn sie von keiner Anwendung empfangen werden, scheint es, als könne Windows eingehende Pakete nicht verarbeiten oder sie zumindest nicht an die entsprechenden Anwendungen übermitteln.

Ich wäre dankbar, wenn jemand meine Argumentation bestätigen oder widerlegen und mir einen Weg zur Lösung dieses Problems weisen könnte. Das Ziel ist, dass mehrere Anwendungen auf demselben Host einem einzigen Multicast-Gruppenkanal beitreten und Nachrichten empfangen können, ohne dass sie auch „Müll“ an die Multicast-Gruppe senden müssen, um Daten empfangen zu können (der Workaround wird als Punkt 4 beschrieben).

Ich verwende Java für die Implementierung und kann auf Anfrage hier ein MWE posten. Ich befürchte jedoch, dass sich dadurch der Fokus vom Szenario auf die Programmierung verlagern könnte, was hier (soweit ich das beurteilen kann) nicht das Thema ist.

Antwort1

Der OP fragt nach einer Methode, um Peers in einem Netzwerk zu entdecken, ohne diese Peers zu kennen, gemäßdiese QuellemDNS erfordert mindestens die Kenntnis des Hostnamens jedes Peers.

Daher ist mDNS in der beschriebenen Form keine praktikable Lösung für dieses Problem.

Nachauf diese Antwort, zum Thema Multicast: Was Sie gefragt haben, ist möglich. Dazu müssen Sie die Socket-Option SO_REUSEADDR verwenden. Wenn Sie diese Socket-Option verwenden, können mehrere Sockets auf derselben Adresse:Port-Kombination lauschen, solange:

  1. Die Adresse ist eine Multicast-Adresse. und
  2. SO_RESUSEADDR wird auf jedem einzelnen Socket gesetzt, der versucht, eine Bindung an die Adresse:Port-Kombination herzustellen.

Doch lautdiese Antwort, müssen Sie möglicherweise auch SO_BROADCAST auf jedem Socket festlegen, was sicherlich nicht intuitiv ist! Bei meinen eigenen Tests mit Python unter Windows musste ich dies jedoch NICHT tun, daher bin ich mir nicht sicher, wie legitim diese Antwort ist. Ich erwähne sie für den Fall, dass Sie nicht weiterkommen, obwohl ich dies als möglicherweise veraltet betrachte. Ich teste derzeit unter Windows 10.

Hier ist ein Beispiel für Code, den ich getestet habe und der keine Fehler erzeugt. Es ist Teil eines automatisierten Tests, der Beacons verwendet, um einen Arbeitsprozess mit einem Brokerprozess zu verbinden. Dieser Test ist erfolgreich, wenn er auf einem einzelnen Knoten ausgeführt wird. Auf mehreren Knoten wurde er noch nicht getestet.

import socket, struct

MCAST_GRP = ''
MCAST_PORT = 1234

MULTICAST_TTL = 2

def create_beacon_listener():

    sock = socket.socket(
        socket.AF_INET,
        socket.SOCK_DGRAM,
        socket.IPPROTO_UDP
    )
    sock.setsockopt(
        socket.SOL_SOCKET,
        socket.SO_REUSEADDR,
        1
    )
    sock.setblocking(0)

    sock.bind(( MCAST_GRP, MCAST_PORT ))

    multicast_grp_req = struct.pack(
        "4sl",
        socket.inet_aton(MCAST_GRP),
        socket.INADDR_ANY
    )

    sock.setsockopt(
        socket.IPPROTO_IP,
        socket.IP_ADD_MEMBERSHIP,
        multicast_grp_req
    )
    
    return sock

Der obige Code gibt einen Abhörsocket für die gewünschte Gruppenadresse MCAST_GRP und den Port MCAST_PORT zurück. Und ja, MCAST_GRP ist auf eine leere Zeichenfolge gesetzt, was bedeutet, dass Sie tatsächlich alle Multicast-Adressgruppen abhören. Dies scheint entweder eine Einschränkung in Windows oder meines Wissens wahrscheinlich in letzterem zu sein.

In jedem Fall führt die Verwendung einer bestimmten Adresse in der MCAST_GRP-Variable zu einem Fehler. Wenn Sie also eine leere Zeichenfolge verwenden, erhalten Sie zumindest den Code, der das vom OP beschriebene Problem löst.

Dieser Code kann innerhalb desselben Prozesses mehrmals wiederverwendet werden, obwohl ich noch nicht getestet habe, ob mehrere Prozesse ihn erfolgreich verwenden können. Ich habe ihn mit dem Asyncio-Framework von Python getestet, also mit mehreren Sockets, die im selben Thread lauschen.

Nebenbei bemerkt: Zur plattformübergreifenden Unterstützung können Sie diesen Code auch auf Nix-Betriebssystemen zum Laufen bringen und auf diesen Systemen MCAST_GRP auf eine bestimmte Adresse einstellen.

BEARBEITEN:

Ich bin vor kurzem aufdiese Ressource von MSDies ist ein Beispiel, das die Verwendung einer bestimmten Multicast-Gruppenadresse zulässt, anstatt sie an alle zu binden. Dazu müssen einige weitere Optionen in der Variable multicast_grp_req festgelegt werden. Das Beispiel ist außerdem C++-Code, nicht Python, aber sie sind ähnlich genug, um das Wesentliche zu verstehen.

Hoffe das hilft :)

verwandte Informationen