Demo-Netzwerk-Spiel

In diesem Beispiel sollst du ein tieferes Verständnis für eine Client-Server-Kommunikation im Rahmen eines einfachen Demo-Netzwerk-Spiels erhalten. Zwei Spieler verbinden sich mit einem Server, anschließend können sie gegeneinander / miteinander spielen.

Screenshot demo-netzwerk spiel.png

Jeder Spieler sendet hierzu seine Änderungs-Wünsche an den Server, dieser leitet sie dann an alle Spieler weiter. Erst die Nachrichten des Servers führen bei den Clients zu sichtbaren Änderungen. So wird sicher gestellt, dass der eigene Spieler nicht flinker auf Eingaben reagiert als der gegnerische Spieler. Hier werden nun folgende Aspekte genauer erklärt:

  • Der Aufbau und die Aufgaben des Servers
  • Der Aufbau und die Aufgaben des Clients
  • Das Protokoll zur Koordination der Netzwerk-Kommunikation
  • Zusammenspiel aller benötigten Komponenten


Klassen-Diagramm

Du siehst hier das Klassen-Diagramm des Demo-Netzwerk-Spiels. Alle rot gefärbten Klassen wirst du selbst erstellen. Alle schwarz gefärbten Klassen stellt dir die Engine Alpha zur Verfügung.

klassendiagramm demo netzwerk spiel.png

Überblick aller benötigten Komponenten

  • Die Spielfigur kannst du prinzipiell gestalten, wie du willst. Hier handelt es sich der Einfachheit halber um einen Kreis in dem der Name des Spielers als Text steht. Die Klasse Spielfigur erbt von der Klasse Knoten um die Einzelteile (Text und Kreis) zu einer Gesamtheit zu gruppieren. Dadurch kann später die Spielfigur als ein Ganzes in die Wurzel des Grafik-Systems eingehängt werden. Auch ihre Bewegung kann so mit nur einem Befehl realisiert werden.
  • Die Klasse MyGameServer realisiert die Server-Instanz des Spiels. Bei ihr müssen sich die Clients anmelden bevor das Spiel beginnen kann. An diese Instanz sendet jeder Spieler später seine Änderungs-Wünsche. Der Server wird diese Wünsche dann an alle angemeldeten Clients verbreiten. Die Klasse MyGameServer hat ein Referenz-Attribut vom Typ Server (aus der Engine Alpha). Hierüber werden die Nachrichten an die Clients gesendet. Um auch Nachrichten empfangen zu können, implementiert die Klasse MyGameServer das Interface Empfaenger (der Engine Alpha), welches einige Methoden vorschreibt zum Empfangen von Nachrichten. Jede dieser Methoden wird später automatisch aufgerufen werden, sobald von der Client-Seite eine Nachricht eingeht.
  • Die Klasse MyGame sorgt für die grafische Darstellung bei jedem der Clients. Deshalb muss sie von der (Engine Alpha) Klasse 'Game erben. Sie verfügt über zwei Referenz-Attribute vom Typ Spielfigur um die eigene Spielfigur und die des Gegners verwalten zu können. Beide Referenzen werden in einem Array verwaltet. Es gibt noch ein drittes Referenz-Attribut der Klasse MyNetworkClient. An dieses MyNetworkClient-Objekt werden die Änderungswünsche (Tastatur-Ereignisse) übergeben und von diesem werden auch die Antworten des Servers (Zustands-Änderungen der Spielfiguren) empfangen. Von der Klasse MyGame muss jeder Spieler eine Instanz erzeugen. (Vorher muss eine MyGameServer-Instanz erzeugt worden sein.)
  • Die Klasse MyNetworkClient ist auf der Client-Seite für die Kommunikation mit dem Server verantwortlich. Sie erbt von der (Engine Alpha) Klasse Client und verfügt dadurch über Methoden zum Senden von Nachrichten zum Server. Die ebenfalls von der Klasse Game geerbten (abstrakten) Methoden zum Empfangen von Nachrichten vom Server müssen mit konkreten Inhalten überschreiben werden. Die Klasse MyNetworkClient hat noch ein Referenz-Attribut vom Typ MyGame. Das ist das Grafik-Fenser, an das die Befehle bzgl. Zustands-Änderungen der Spielfiguren weiter geleitet wird.

Details zur Funktion des Spiels

Aufgaben des Servers

Der Server-Dinst wird zunächst auf einem beliebigen Rechner im Netzwerk gestartet. Von nun an lauscht er auf einem festgelgten Port (oberhlab 1024) auf Verbindungs-Anfragen der Clients. Nach erfolgreicher Verbindung mit den Spiel-Clients nimmt er jeden Wunsch auf Zustands-Änderungen entgegen und verteilt sie an alle Clients, damit diese dann quasi zeitgleich die Änderungen im Grafik-Fenster umsetzen können. Hierzu ist auf Server-Seite ein Server-Protokoll und auf Client-Seite ein Client-Protokoll nötig, die beide weiter unten genauer erläutert werden.

Zustands-Übergangs-Diagramm des Servers:

zustandsdiagramm server.png

Aufgaben des Clients

Ein Client muss sich im Netzwerk zuerst mit dem Server verbinden. Hierzu muss der Client die IP-Adresse (z.B. 192.168.1.100) und den Port (z.B. 1234) des Servers kennen. Nach erfolgreicher Verbindung kann der Client Nachrichten an den Serer schicken. Diese Nachrichten müssen einer vorher festgelegten Struktur folgen - dem Server-Protokoll. Jede Nachricht an den Server wird von diesem an alle Clients weiter geleitet, damit jederzeit jeder Client über dieselbe Informtaion verfügt. Auch die Nachrichten vom Server an die Clients müssen einer festgelegten Struktur folgen - dem Client-Protokoll. Diese neu ankommenden Informationen werden auf Client-Seite dann in grafische Änderungen (gemäß dem Client-Protokoll) umgesetzt. Beide Protokolle werden im nächsten Punkt genauer erläutert.

Ein Protokoll zur Koordination der Netzwerk-Kommunikation

Client und Server können nicht beliebige Nachrichten austauschen. Erst wenn beide Seiten dieselbe Sprache sprechen, kann eine sinnvolle Kommunikation erfolgen. Ein Protokoll legt den genauen Aufbau der erlaubten Befehle fest. Es kann ein Protokoll auf Server-Seite und ein anderes auf Client-Seite geben.

  • Bei unserem Demo-Netzwerk-Spiel gibt es nur drei verschiedene Befehle, die an den Server gesendet werden dürfen.
    • anmelden:name
    • bewegen:index:dx:dy
    • farbwechsel:index:farbe
  • Auf Client-Seite sieht das Protokoll ebenfalls drei Befehle vor:
    • neu:name:index:x:y
    • bewegen:index:dx:dy
    • farbwechsel:index:farbe

Wei man leidcht erkennt, sind zwei der Befehle auf beiden Seiten identisch. Den dritten Befehl gibt es jeweils nur auf einer Seite. Dabei stellen die Doppelpunkte Trennzeichen zwischen den einzelnen Bestandteilen eines Befehls dar. Der erste Teil jedes Befehls gibt die Art des Befehls an, die kursiv geschriebenen weiteren Teile sind (verpflichtende) Parameter, für die in jedem konkreten Fall entsprechende Werte eingesetzt werden müssen. name ist der Name des Spielers. index ist eine für jeden Client eindeutige Zahl (Index im Array) zu deren Unterscheidung. x und y sind die Start-Koordinaten eines Spielers. dx und dy sind die Schrittweiten der Bewegung.

Sequenz-Diagramm zum Anmelden der Clients beim Server:

sequenzdiagramm anmelden.png

Sequenz-Diagramm zum Bewegen eines Spielers:

sequenzdiagramm bewegen.png

Das Sequenz-Diagramm zum Ändern der Farbe eines Spielers ist analog aufgebaut.

Demo-Projekt


Erweiterungs-Möglichkeiten

Das Spiel hat bisher keinen Sinn. Man kann nur die Spieler bewegen und deren Farbe ändern. Selbst ein sauberes Beenden des Spiels ist noch nicht implementiert.

  • Erweitere das Protokoll um einen vierten Befehl zum Abmelden.
    Sendet ein Client dem Server eine Nachricht zum Abmelden, so wird diese vom Server an beide Clients weiter gereicht. Daraufhin beendet der Server die Verbindung zu beiden Clients. (Die Clients werden daraufhin automatisch ihre Verbindung zum Server schließen.
  • weitere Features wie z.B. eine Kollisions-Kontrolle solltest du dem Server überlassen.
    Würdest du sie in den Clients implementieren, so würde die Kollision zwei Mal festgestellt und dem Server übermittelt werden. Auch weitere (automatisch bewegte) Spielfiguren musst du vom Server steuern lassen ...