[39dll] UDP/LAN Serverbrowser

    • GM 8

      [39dll] UDP/LAN Serverbrowser

      Guten Morgen die Herrschaften!

      Nachdem ich vor Kurzem selbst die Vorteile und verschiedene Nutzungsmöglichkeiten des UDP-Protokolls kennengelernt habe, habe ich mich dazu entschlossen, hier eine kurze UDP Erklärung in Form eines LAN Serverbrowsers zu machen. Die Beschreibungen hier sind auf erfahrenere Nutzer der 39dll ausgelegt und erklären keinesfalls alle kompletten Schritte.


      Wozu?
      Jeder, der bereits mit beidem, Game Makers internem Mplay als auch mit der 39dll gearbeitet hat, weiß: Mit den Game Maker internen Funktionen ist es sehr einfach, einen LAN-Serverbrowser zu machen, da die Funktionen dafür gegeben sind. Die Funktionen sind in der 39dll auch gegeben, nur muss man ein bisschen mehr Aufwand in Kauf nehmen, da diese nicht automatisiert sind.


      Wie funktioniert das?
      Grundsätzlich wird ein Serverbrowser, der im LAN funktioniert höchstwahrscheinlich auf UDP und Broadcasting setzen.
      UDP ist ein Netzwerkprotokoll, das der Game Maker intern nicht direkt unterstützt, sehr wohl aber verwendet (um u.a. das Finden von LAN Servern zu ermöglichen). Im Gegensatz zu TCP, was die meisten von euch vermutlich verwenden, wenn sie ein Netzwerkspiel programmieren, benötigt UDP keine direkte aktive Verbindung. Das heißt, man muss sich nicht vorher mit einem Server verbinden, um an einen anderen Computer Nachrichten zu verschicken. Außerdem sind Nachrichten, die via UDP verschickt werden nicht gegen Datenverlust abgesichert, das heißt, es gibt keine Garantie, dass die Nachricht auch beim Empfänger ankommt. Dafür sind Nachrichten, basierend auf UDP wesentlich schneller und können so für Übertragungen eingesetzt werden, die kontinuierlich erfolgen und bei denen es nicht sehr schlimm ist, wenn mal ein Paket verloren geht (z.b. die Richtung in die ein Spieler sieht). Dadurch, dass keine Verbindung benötigt
      wird, kann man also Nachrichten an IP-Adressen verschicken, ohne zu wissen, ob diese erreichbar sind.
      Nun kommt Broadcasting ins Spiel. Um nicht an alle möglichen Adressen im eigenen LAN Nachrichten schicken zu müssen, um zu prüfen, ob diese aktiv sind, gibt es etwas, das Broadcast Adresse genannt wird. Das ist eine
      spezielle IP-Adresse welche Nachrichten, die an diese Adresse geschickt werden zu allen sich im Netzwerk befindenden Rechner weiterleitet. Die Broadcast IP setzt sich aus der Basis Netzadresse des Computers und der negierten Subnetzmaske zusammen, wobei beide bitweise or-verknüpft werden.

      Beispiel: Mein Computer hat die Netzwerkadresse 192.168.0.5, die Subnetzmaske ist 255.255.255.0, die negierte Subnetzmaske ist 0.0.0.255.
      Verknüpft mit einem bitweisen OR erhalte ich daraus 192.168.0.255.
      Die 39dll besitzt von Grund auf nicht die Möglichkeit, die Subnetzmaske zu ermitteln, dafür habe ich die dll um erwähnte Funktion erweitert und werde sie hier verlinken.


      Legen wir los!

      Ladet die modifizierte DLL und erstellt ein neues Projek. Importiert die Scripts, erstellt ein Objekt das für den Serverbrowser zuständig ist und eins, dass den Server darstellt.
      Nach dem Initialisieren der DLL benötigen wir erstmal einen UDP Socket, über den wir später Nachrichten versenden und empfangen.
      Dazu benutzen wir:

      GML-Quellcode

      1. global.sock_broadcast = udpconnect(14804, 1)

      Das erste Argument gibt den Port an, der benutzt werden soll, das zweite ist wie bei tcpconnect der blocking mode. Hier sei vielleicht noch erwähnt, dass man einen UDP Socket auf den gleichen Port wie einen TCP Socket legen kann, so spart man sich bei Internetübertragungen unter Umständen das Freigeben von mehreren Ports.

      Außerdem lassen wir uns die Broadcastadresse berechnen:

      GML-Quellcode

      1. my_ip = hostip(myhost());
      2. subnet = getsubnetmask();
      3. global.broadcast_ip = uinttoip(iptouint(my_ip) | ~iptouint(subnet));

      | und ~ sind binäre Operatoren wobei | das bitweise OR und ~ das bitweise Negieren sind. Damit wir die IP negieren und verknüpfen können müssen sie zuerst in Zahlen umgewandelt werden. Danach wird der Wert wieder in einen String umgewandelt.

      Wir haben jetzt also einen einsatzbereiten Socket. Erstellt irgendein Menü, indem man auswählen kann, ob man Server suchen möchte oder hosten und unterscheidet erstmal mit einer Variable, ob man hostet oder nicht, für einen Test, muss kein wirklicher Server offen sein.
      Will der Spieler nun Server suchen, machen wir folgendes: Über den UDP Socket senden wir eine Broadcast Nachricht mit der Aufforderung, uns alle offenen Server zukommen zu lassen. Das sieht im einfachsten Fall so aus:

      GML-Quellcode

      1. clearbuffer()
      2. writebyte(1) // Message ID
      3. sendmessage(global.sock_broadcast, global.broadcast_ip, 14804);

      Das Nachrichten-Versenden sieht also ziemlich ähnlich aus, wie wenn man über TCP versendet, mit der Ausnahme, dass man hier zusätzlich die IP und den Port angibt, an den man senden will, da unser UDP Socket ja keine direkte Verbindung darstellt.

      Nun wird es Zeit, dass wir, falls wir einen Server hosten, auf diese Broadcast Nachrichten reagieren.
      Dies erfordert die bekannte Nachrichten-Schleife:

      GML-Quellcode

      1. s = receivemessage(global.sock_broadcast);
      2. if (s > 0)
      3. {
      4. m = readbyte();
      5. switch (m)
      6. {
      7. case 1:
      8. clearbuffer();
      9. writebyte(1);
      10. // Serverinformation hier einfügen, zb. Port, Name etc.
      11. sendmessage(global.sock_udp, lastinIP(), 14804);
      12. break;
      13. }
      14. }

      Ihr seht, ein ganz einfaches Gerüst. Bekommt der Server eine dieser Nachrichten, schickt er eine Nachricht mit Serverinformationen an den Client, der sie angefragt hat. Dazu benutzen wir lastinIP() welches die IP-Adresse des letzten Verbindungs- oder Nachrichtenvorgangs ermittelt. In diesem Fall ist das die IP des Absenders der letzten erhaltenen Nachricht.
      Nun benötigt nur noch der Client eine ähnliche Nachrichten-Schleife, in der er dann die Serverinformationen speichert und für die Darstellung in einer Liste o.Ä. benutzt.


      Abschließende Informationen

      Ich hoffe, ich konnte euch UDP ein bisschen näher bringen, es sei noch etwas gesagt, bevor sich Leute beschweren, dass es nicht funktioniert: Nachdem ein Port an einem PC nur einmal belegt werden kann, lässt sich dieses Programm nicht testen, indem man es zweimal auf dem selben PC öffnet, da es die gleichen Portnummern für den Broadcast vorraussetzt.

      © 2008 by Teamgrill Productions

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „MasterXY“ ()