Lösung für die Entdeckung leichter LAN-Peers?

9

Ich habe eine Bibliothek für die rein plattformübergreifende Programmierung erstellt. Meine damit erstellten Spiele laufen einwandfrei unter Android, PC, Linux, Mac usw.

Die Netzwerkfunktionen werden von der ENET-Bibliothek bereitgestellt. Daher ist die gesamte Kommunikation zwischen meinen Apps nicht TCP- oder UDP-kompatibel, sondern nur im benutzerdefinierten Protokoll, auch wenn es letztendlich schwierig ist, auf dem UDP zu basieren.

Ich denke nicht, dass es möglich ist, mit ENET zu tun, was ich will, deshalb bitte ich hier um Hilfe!

Nehmen wir an, ich habe das gleiche Spiel auf meinem Android-Handy, meinem Laptop und meinem PC. Sie befinden sich alle im selben WLAN-Netzwerk und daher in einem LAN, unabhängig davon, ob es sich um einen WLAN-Hotspot (?) Oder einen Haushaltsrouter handelt.

Ich brauche jeden dieser 3 Peers, um die anderen beiden im Netzwerk zu entdecken. Dies ist nur dazu gedacht, die IP von lebendigen Apps im LAN-Netzwerk zu finden, um Multiplayer-Spiele zwischen ihnen hosten zu können.

Ich kann mir nur einen effektiven Weg vorstellen, UDP-Broadcast, Antworten abwarten, aber wenn das die Lösung ist, brauche ich etwas Kleines, da dies der einzige Zweck der Implementierung ist.

Eine andere Möglichkeit könnte sein, zu versuchen, eine Verbindung zu allen IPs im LAN-Adress-Unterbereich herzustellen, aber ich glaube nicht, dass das Betriebssystem in diesem Fall bei mir sein würde: p

Grimshaw
quelle
2
Ich denke, ein paar UDP-Sendungen sind der richtige Weg, und ich verstehe Ihre Einwände nicht, oder unterstützt ENET keine Sendungen?
Roy T.
Genau das tut es nicht, es kann nur an bereits bekannte Kollegen gesendet werden.
Grimshaw
stackoverflow.com/questions/683624/… Beeinflusst dies eine Antwort?
Grimshaw

Antworten:

5

Wie viele Leute gesagt haben, wäre die Lösung die Verwendung von UDP-Broadcast , aber es gibt viele Implementierungsdetails. Ich bin kürzlich auf dasselbe Problem gestoßen, und nachdem ich eine Lösung ausgearbeitet habe, habe ich einen Blog-Beitrag und ein Beispielprojekt in Form eines LAN-Chat-Servers / Clients erstellt. Ich werde diese hier zusammenfassen, aber Sie sollten sie für weitere Details und echten Code überprüfen.

So funktioniert es, basierend auf einer Beschreibung von Lee Salzman, dem Erfinder von ENet:

  • Ihr Spieleserver wird auf einem Socket als ENet-Host ausgeführt
  • Der Server bindet auch an einen bekannten "Listen" -Port als regulären UDP-Socket (dh nicht an einen ENet-Host).
  • Der Client sendet eine UDP-Broadcast-Nachricht (dh IP 255.255.255.255) an diesen Listen-Port und wartet auf Antworten
  • Alle Server im LAN empfangen diese "Scan" -Nachricht und antworten. Idealerweise können Sie mit dem Port antworten, auf dem der Spieleserver (ENet-Host) ausgeführt wird. Auf diese Weise muss Ihr Spieleserver nicht an einem festen Port ausgeführt werden.
  • Nachdem der Client einige Antworten erhalten hat, weiß er, welche Server vorhanden sind. Anschließend können Sie einen von ihnen als regulären ENet-Peer auswählen, zu dem eine Verbindung hergestellt werden soll. Zu diesem Zeitpunkt benötigt der Client den UDP-Scanner-Socket nicht mehr.

Die gute Nachricht ist, dass ENet Wrapper-Funktionen für die Verwendung von Sockets bietet , sodass Sie alles in ENet ausführen können. Die schlechte Nachricht ist, dass die Hülle extrem dünn ist; Sie müssen über die Socket-Programmierung Bescheid wissen , z select(). Aus diesem Grund empfehle ich Ihnen, sich den Blog-Beitrag und das Beispielprojekt anzusehen, damit Sie den Code kopieren / einfügen und sich viel Zeit sparen können.

Hier sind einige Hinweise und Fallstricke, falls Sie sich für eine eigene Implementierung entscheiden sollten:

  • Der Listener / Scanner muss UDP sein, daher müssen Sie sie mit enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(oder SOCK_DGRAMfür die einfache alte Socket-Programmierung) erstellen.
  • Erlauben Sie für den Server "Listener", dass die Portadresse mit enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(oder SO_REUSEADDR) wiederverwendet wird, damit mehrere Server auf derselben IP ausgeführt werden können
  • Für den Client- "Scanner" müssen Sie Broadcasts auf dem UDP-Socket mit enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(oder SO_BROADCAST) aktivieren , andernfalls können Sie nicht an die Broadcast-Adresse senden. Dies ist nur eine Sicherheitsfunktion , um das versehentliche Überfluten des Netzwerks zu erschweren.

Leider ist dies nicht gerade eine "leichte" Lösung; Das Beispielprojekt erreicht insgesamt einige hundert LOC. Es wäre schön, wenn dies in eine Dienstprogrammbibliothek für ENet gepackt wäre, aber ich habe festgestellt, dass Sie für Spieleserver häufig weitere spielspezifische Informationen mit der Serverantwort senden möchten, um dies nützlich zu machen, z.

  • Der Spieltyp (zB "Koop", "Deathmatch")
  • Die "Karte", "Ebene" oder "Kampagne", die der Server ausführt
  • Die Anzahl der Spieler und die maximale Anzahl der Spieler für den Server
  • Alle anderen spielspezifischen Informationen, die sich auf die Entscheidung des Kunden auswirken, eine Verbindung herzustellen oder nicht. Denken Sie an die "Server-Browser" in Spielen und an die Art der Informationen, die sie anzeigen.
Congusbongus
quelle
Genau das habe ich mir gedacht. Rundfunk ist der richtige Weg.
Lolums
3

Wenn Sie Ihre Bibliothek nicht verlassen möchten, können Sie einfach Brute-Force verwenden und versuchen, eine Verbindung zu jeder der möglichen Adressen herzustellen. Die meisten Heim-LANs sind Class-C-Netzwerke (/ 24), in denen die ersten 24 Bit der IP-Adresse identisch sind und die letzten 8 Bit unterschiedlich sind. Sie haben also nur 255 mögliche IP-Adressen.

Dennoch wäre eine UDP-Übertragung die sauberere Alternative. Senden Sie einfach ein UDP-Paket an 255.255.255.255, und alle Clients hinter demselben Router erhalten es. Sie können dann eine Antwort an die Quell-IP und den Quellport des Pakets senden, um den Absender darüber zu informieren, dass sie vorhanden sind.

Philipp
quelle
2
Bitte, bitte, bitte, bitte, bitte nicht brutal.
Trevor Powell
@ TrevorPowell ... weil ...?
Philipp
2
Weil es die falsche Lösung ist. Es funktioniert nicht an Universitäten (die keine Class-C-Netzwerke verwenden) oder in Unternehmen (die normalerweise auch keine Class-C-Netzwerke verwenden), und die IT-Mitarbeiter von beiden werden die Belastung, die jeder Spieler verursacht, nicht mögen Brute-Force versucht, jedes Mal, wenn sie auf die Schaltfläche "Aktualisieren" klicken, Nachrichten an jede IP-Adresse in ihrem Netzwerk zu senden. Es ist nur eine schlechte Lösung für das Problem . Diese Frage, potenzielle Kollegen ohne einen Mathematikserver zu finden, ist genau das, wofür Broadcast gedacht ist. Verwenden Sie Broadcast. Es ist in jeder Hinsicht besser. :)
Trevor Powell
1

Sie können sich DNS-SD / ZeroConf / Avahi / Bonjour / mDNS ansehen . Es ist das Material, mit dem Apple Drucker, iTunes-Ordner usw. freigibt, aber es wurde an anderer Stelle übernommen. Avahi ist die OpenSource-Version, die Linux verwendet (nicht sicher, ob es nur Linux ist), nicht sicher, wie portabel das Ganze ist (obwohl es Implementierungen für die meisten Plattformen gibt).

Trotzdem ist es wahrscheinlich einfacher, nur die UDP-Übertragung durchzuführen.

David C. Bishop
quelle