Synchronisieren von Objekten über Client/Server - bester Weg?

Kjubert

Aktives Mitglied
Hallo zusammen,

in Netzwerkprogrammierung bin ich bis auf kleinere Versuche noch Grünschnabel, habe aber Böcke (und Anlass) mir da jetzt mal einige Sachen anzusehen.
Es geht konkret um eine Idee zu einer speziellen Form von Multiplayer-Spiel, von der ich relativ begeistert bin - ich habe diesen Ansatz erst einmal bei einem Spiel gesehen und fand ihn ziemlich cool - ich erklärs mal kurz und hoffe dann auf hilfreiche konzeptuelle Ideen:

Das Spiel setzt voraus, dass die Spielenden die Spielregeln selbst beherrschen und implementiert daher keinerlei Regelmechanik, sondern wirklich ausschließlich die Spielmaterialien (z.B. Tisch, Karten, Spielsteine, etc.). Die beteiligten Spieler können einfach als ob sie zusammen am Tisch sitzen mit den Materialien, die zum Spiel gehören, spielen.
Und jetzt kommts - ich hab da à la Kochsendung nämlich schonmal was vorbereitet:
Zwei Dinge schweben mir vor - einmal eine Scrabble-Implementation, die einfach die Spielfläche und die Steine sowie eine verdeckte Ablage für die "Hand"-Steine der einzelnen Spieler bereitstellt. Das Spiel lässt die Spieler einfach Plättchen legen wie sie wollen - denn die Regeln können die ja. Ich finde diesen Ansatz zeimlich cool - natürlich ist das nicht bei jedem Spielkonzept die passende Lösung, hier schon. Guckt mal hier:

xs6xn39l.jpg



Das zweite wären klassische Kartenspiele: Ich habe eine hübsche Spielfläche und die Möglichkeit einfach Karten-Stapel auf den Tisch zu legen, die verschoben werden können und von denen man Karten aufdecken und ziehen kann, die man dann auf der Spielfläche hin und herschieben kann wie man will. Die Spieler überlegen sich dann selbst, welches Spiel sie daimt spielen. Ein virtueller Kartentisch sozusagen. Natürlich mit Chatfunktion fürs Streiten und Meckern 😉
Hier mal ein Screen:

x6xq87ef.jpg



...nun zu meinem Problem: Ich habe die Netzwerkkommunikation noch nicht gemacht, will erstmal nach dem besten Ansatz forschen. Meine Ideen sind bisher ganz grob folgende:
Die Objekte, die auf dem Tisch liegen, könnte man serialisiert an alle Clients broadcasten. Bei dem Scrabble-Beispiel sind da KEINE Grafiken drin, wär also wohl OK. Bei den Karten müsste man mal sehn.
Ist Serialisierung überhaupt der richtige Weg? Die Datenmengen werden ja wohl nicht groß sein.
Könnte man bei Objekten mit Bildern die Bilder bei der Serialisierung weglassen? Es wär ja blöde die mitzusenden.
Wär es möglich eine Art Echtzeitdarstellung zu bekommen? z.B. wenigstens in einem Intervall von 1 Sekunde eine Aktualisierung der Darstellung abhängig von dem Client, der gerade "am Zug" ist?
Wie kann ich der Client-Anwendung am schönsten mitteilen, dass irgendwelche Komponenten verändert wurden, ohne eine Referenz auf diese "Client-Parent-Anwendung" in meinen Spiel-Objekten zu haben? Er serialisiert mir ja sonst immer den ganzen Client mit...

Naja das ist etwas wirr, aber hoffentlich wird irgendwie klar, worauf ich hinaus will. Sorry für die vielen Wörter - aber hey - es sind auch 2 Bilder dabei, also nicht über trockene Lektüre beschweren 😉
 
Das Konzept hängt jetzt bisserl davon ab, ob sich die Clients selber untereinander vernetzen sollen oder ob das nicht doch besser über einen zentralen Spieleserver gehen soll (im Ernstfall kann ja der Spieleröffner den Server spielen).

Aber grundsätzlich würde ich nicht über Serialisierung sondern platt über DataInput/OutputStream gehen (also eigenes Protokoll).

Wenn Du viele Events verschickst (also zb. zeigen willst, wie ein Spieler seinen Stein/Karte auf dem Brett bewegt) musst Du auf jeden Fall noch ein Event einbauen für die entgültige Ablage der Karte um zu viele Move-Events vorher ggf. wegwerfen zu können.

Ich würde für mich eher die Probleme in der GUI als in der Netzwerkkommunikation sehen - was daran liegen mag, dass ich wenig GUI aber viel Netzwerk mache.

Bernd
 
Das Konzept hängt jetzt bisserl davon ab, ob sich die Clients selber untereinander vernetzen sollen oder ob das nicht doch besser über einen zentralen Spieleserver gehen soll (im Ernstfall kann ja der Spieleröffner den Server spielen).

So hab ichs mir auch vorgestellt, ja.

Aber grundsätzlich würde ich nicht über Serialisierung sondern platt über DataInput/OutputStream gehen (also eigenes Protokoll).

Hm. Im Prinzip sind die Objekte alle recht leicht formalisierbar, könnte man also machen. Aber dennoch ist Serialisierung ja erstmal abstrakter, müsste mir da erstmal weniger kopp drum machen. Spricht denn generell was dagegen?
 
Hm. Im Prinzip sind die Objekte alle recht leicht formalisierbar, könnte man also machen. Aber dennoch ist Serialisierung ja erstmal abstrakter, müsste mir da erstmal weniger kopp drum machen. Spricht denn generell was dagegen?

Eigentlich nur 2 Probleme - die tauchen leider erst dann auf, wenn man es nicht mehr gebrauchen kann.

1) Du musst die Transportobjekte überall gleich haben, sonst stimmt die SerialID nicht mehr. Wenn also ein Client eventuell eine ältere Version hat, dann bekommt er eine dämliche Fehlermeldung und darf erstmal updaten. Ein eigenes Protokoll hätte den Vorteil, dass der Server ggf. je nach Clientversion auch unterschiedliche Versionen verschickt.

2) Das leidige Problem mit HandleTable (such mal hier im Forum): Wenn Du ständig Objekte über die Object-Streams versendest läuft das über und Du darfst einen reset() machen der unter Umständen tierisch langsam ist.

Ich hab früher auch alles serialisiert über Sockets verschickt was bei Drei nicht auf den Bäumen war - nach dem schlimmsten Rollout meines Lebens vor 12 Jahren mach ich das ganz devot zu Fuss.

Hat auch bisserl den Charme, dass man sich genau überlegt was man da eigentlich über die Leitung schickt und dann denkt "naja, die 15MB müssen nicht wirklich sein".

Bernd
 
Und vielleicht ists ja auch ne ganz nette Übung, stimmt schon. Ich muss mal sehn. Vielleicht lös ichs auch erstmal mit Serialisierung und baus später um. Dann hab ich beides mal gemacht.

Das Problem mit den SerialIDs nehm ich nicht so ernst... erstens pfleg ich die nicht (default 😳) und zweitens sollte das erstmal ein Testprojekt werden... an den Markt geh ich damit vielleicht später 😉

Aber danke schonmal für die Anregungen!

Zum Ablauf der ganzen Sache fehlt mir noch die entscheidende Idee... Soll es überhaupt "Züge" geben? Oder alles komplett in Echtzeit und alle können machen was sie wollen (würde der Idee gerechter werden). Aber was ist dann, wenn zwei Laute das gleiche Objekt gleichzeitig benutzen -> problematisch?
Fragen über Fragen...
 
Das Problem mit den SerialIDs nehm ich nicht so ernst... erstens pfleg ich die nicht (default 😳) [,,,]

Genau da ist ja das Problem: Sobald Du irgendwas an der Klasse änderst, ändert sich die ID und schon knallt es an unerwarteter Stelle. Dann fängt man erst an, eine fixe ID in die Klasse zu schreiben um banale Änderungen kompatibel zu halten und dann writeObject/readObject zu überschreiben um die Kompatibilität zu wahren.

Ist einfach nur ein Erfahrungwert, ich würde wahrscheinlich aber auch erstmal die Klassen "pur" serialisiert durch die Gegend schieben um ein Gefühl für den Ablauf zu bekommen.

Zum Ablauf der ganzen Sache fehlt mir noch die entscheidende Idee... Soll es überhaupt "Züge" geben? Oder alles komplett in Echtzeit und alle können machen was sie wollen (würde der Idee gerechter werden). Aber was ist dann, wenn zwei Laute das gleiche Objekt gleichzeitig benutzen -> problematisch?

Ja nun - die Spielregeln schreiben normalerweise vor, dass nur einer der Spieler am Zug ist. In sofern musst Du ja "nur" die Zugreihenfolge bestimmen und auswürfeln, wer als erstes am Zug ist.

Bei Scrabble wäre es natürlich eine nette Idee, wenn die Clients (also Spieler) ihre Buchstaben auf ihrem Board verschieben können um mit Worten zu experiementieren. Diesen Status des Boards (also wo welches Tile liegt, natürlich ohne den Buchstaben zu zeigen) an die Mitspieler zu vermitteln wäre natürlich schick.

Bernd
 
Für Statusreplikation über verschiedene Protokolle (abhängig von der Infrastruktur) kann ich JGroups empfehlen. Konzipiert war es für LANs und WANs, aber abhängig vom Protokoll kann man auch im Internet damit gute Ergebnisse erzielen. Dazu muss man aber u.U. seine Infrastruktur darauf abstimmen, also keine reine Client-Client Kommunikation verwenden sondern noch eine Serverimplementierung als Vermittler dazwischen setzen.
 
Na da bietet sich doch RPC (RMI, SIMON, ...) bestens an. Da wird zwar auch serialisiert, aber wer sagt dass man megabyte große Objekte hin und herschieben muss? Die Grafik darf ja durchaus beim Client liegen. Und der muss dann nur noch Methoden am Server aufrufen. Wenn man UI von der Logik entkoppelt (was so oder so empfehlenswert ist), dann ist die Objekthierarchie auch ziemlich klein und der Übertragungsoverhead dementsprechend gering.

Mal davon abgesehen: Wenn man mehr Primitive als Objekte verschickt (oder sogar nur primitive), hat man auch weniger das Problem mit der Serialisierung.

- Alex
 

Zurück
Oben