Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#36

Re: Pokerprojekt realisierung

  Alt 6. Apr 2007, 09:41
Zitat von .chicken:
Klappt soweit auch, nur weiss ich nicht, wie ich den Array der Spieler versenden soll.
Alle anderen Werte sind ja nur Integer bzw Strings und auhc nur einzelne Werte!+
Das ist ja ein Array eines bestimmten Typs!
Du musst ein wenig von der Speicherstruktur abstrahieren. Wie bereits erwähnt kann man nicht einfach eine ganze Klasse verschicken, sondern muss diese serialisieren (genauer kann man überhaupt nur serialisierbare Klassen verschicken). Die Frage ist ob Du wirklich all das brauchst. Die Informationen, die Du hast sind sehr viel einfacher, Du musst nur das verschicken, was von einem Spieler wirklich allen bekannt sein muss. Das wären (denke ich) nur der Name, der aktuelle Chip-Stand und ggf. noch die Position am Tisch.
Tritt ein neuer Spieler dem Spiel bei, so muss allen "alten" Spielern nur ein Datum (der neue Spieler) mitgeteilt werden. Umgekehrt muss dieser neue Spieler natürlich auch die Daten von allen "alten" Spielern bekommen. Das ganze machst Du einfach, in dem Du nacheinander die einzelnen Spieler an ihn schickst. Natürlich kannst Du auch direkt ein komplettes Array verschicken (minimiert den Overhead), aber das ist für Dein Spiel nicht zwingend nötig (werden ja kaum 1000e Spieler auf einem Server sein und kann man auch nachträglich ändern).

Zitat von .chicken:
Also so sehen die Typen aus und ich muss jetzt vom ServerSocket irgendwie die Spieler auf dem ClientSocket aktualisiern lassen. Wie mache ich das am besten? Weil mit SendText wärn das ja dann doch ziemlich viele Nachrichten!
Ziemlich viele Nachrichten ist sehr relativ. Textnachrichten haben einen sehr einfachen Vorteil, Du hast etwas das sehr unabhängig von Sender und Empfänger ist. Damit hast Du zwar die doppelte Umwandlung, für heutige Systeme sollte die aber (bei der zu erwartenden Menge von Nachrichten) kaum ins Gewicht fallen.
Die Frage ist, ob Du wirklich so viele Nachrichten verschicken musst, wie Du fürchtest. Letztlich solltest Du immer nur die Information verschicken, die gerade benötigt wird. Dazu solltest Du Dir einfach mal anschauen, was alles passieren kann:
  • Spiel wird eröffnet, noch gar nichts passiert (der Server kennt schon alle Daten)
  • Spieler tritt Spiel bei
  • Spiel wird begonnen
  • Spieler ist dran
  • Spieler setzt
  • Hand wird gegeben
  • Flop wird gegeben (auch einzelne weitere Karten)
  • Spiel endet

Ganz grob wären das die ersten Dinge, die mir einfallen. Das sind schon nicht so viele Nachrichten (imho). Jetzt wäre die Frage, welche Information zu welchem Ereignis gehört.
Bei der Eröffnung ist nichts zu tun, da findet alles lokal statt und der Server kennt die Daten natürlich schon.
Tritt nun ein Spieler dem Spiel bei, so interessieren nur die genannten Informationen, wo sitzt der Spieler, wieviel Geld hat er und wie heißt er. Im Gegenzug bekommt dieser Spieler die gleichen Daten aller anderen Spieler.
Wird eine Runde begonnen, so erhält ein Spieler den Dealer-Button (es wird also die Reihenfolge festgelegt). Zudem müssen zwei Spieler den Big bzw. Small-Blind setzen. Das ist dann eine Aufforderung (Nachricht) an je einen Spieler. Im Gegenzug muss das setzen bestätigt werden.
Dann werden die Hände gegeben und ein Spieler bekommt die Nachricht, dass er dran ist. Nun hat er die Auswahl, was genau er machen möchte (Setzen, Callen, Passen, ...). Was auch immer gemacht wird ist nur eine Nachricht von einem Spieler. Wurde die Aktion ausgeführt, so verliert der Spieler das Recht etwas zu machen und jmd. anderes bekommt die Nachricht, dass er dran ist.
Der Server merkt sich dabei, wann eine Runde zu enden ist. Dabei kann es sein, dass sich der Flop ändert. Hier muss allen Spieler die Information der neuen Karten (und ggf. Position) mitgeteilt werden, also max. 3 Nachrichten auf einmal.
Zu guter Letzt gibt es noch das Ende eines Spiels. Hier wird dann mitgeteilt, wer gewonnen hat, dieser Person wird sein Gewinn übermittelt und ggf. werden den Spielern die aufgedeckten Karten mitgeteilt.
(ist nicht ganz vollständig, aber halt so grob der Ansatz).

Der Letzte Punkt dürfe die meisten Nachrichten produzieren, hier kannst Du also gut abschätzen, wie groß die Menge der Nachrichten maximal wird. Dazu muss natürlich feststehen, in welcher Form Du Nachrichten überträgst. Wichtig ist, dass jede Nachricht eindeutig identifiziert werden kann (es macht einen Unteschied, ob man die Karten des Flops sieht oder die aufgedeckten des Gegners). Diese Identifikation kannst Du durch Konstanten festlegen. Da kämen Cardinal/Integer Werte (4 Byte) oder eindeutige Strings in Frage. Bei Strings hängt die Größe von der Länge des Strings ab. Sagen wir mal, deine Konstanten bestehen aus max. 50 Zeichen (sollten eigentlich deutlich weniger werden, oder?), dann wären das 50 Byte pro String.
Dann haben wir noch die eigentlichen Werte. Auch hier können wir die größte Nachricht abschätzen. Das dürften solche sein, bei denen ein Spieler (Spielername dominiert mit seiner Größe), Karten aufdeckt. Sagen wir auch, dass Du für Spielernamen nur eine Länge von 50 Zeichen zulässt, also wieder 50 Byte. Eine Karte besteht aus einer Farbe und einem Wert. Sehr großzügig schätze ich auch diese Information mit 50 Byte ab. Insgesamt würde also das größte Datum hier 200 Byte enthalten. Das ganze wird jetzt für jeden Spieler verschickt und auch noch an jeden Spieler. Schätzen wir mal die Spielerzahl mit 20 ab, dann hätten wir also max. 20*20*200 Byte, also < 80 KByte. Dabei habe ich hier schon sehr sehr großzügig abgeschätzt und das ist der gesamte Traffic für diese Nachricht, wenn Du sie für jeden Spieler abschickst (also noch 20 Spieler im Spiel waren) und jeder sie empfängt. Pro Spieler kommen nur 4000 Byte (< 4 KByte) an, die meisten Webseiten dürften deutlich größer sein.
An sich dürftest Du sogar sehr viel kleinere Werte erwarten, da kaum jmd. ernsthaft 50 Zeichen im Namen hat oder diese für die Identifikation einer Karte benötigt werden.
Natürlich kannst Du auch Karten, Beträge und die Identifikation der Nachricht in einem Cardinal/Integer Wert speichern, dann nehmen diese konstant nur noch 4 Byte ein. Das gleiche geht sogar mit den Spielern, dabei musst Du nur einmal die Assoziation zwischen Spielername und Nummer mitteilen und bei jedem Spieler speichern, dann kannst Du auch anhand der Nummer den Spieler ermitteln, an sich sollte das aber einfach nicht nötig sein.

Wie gesagt, ich denke so richtig viele Nachrichten sind es nicht und es ist der leichteste Weg. Natürlich kannst Du auch die Spieler serialisieren und die komplette Information verschicken. Dies bringt aber deutlich größere Strukturen mit sich und macht das Erweitern und die Fehlersuche imho etwas schwerer.

Zitat von .chicken:
Edit: Sollt ich mich vielleicht doch in die IndyKomponenten einarbeiten? Ist das damit einfacher zu realisieren?
Die Indys ändern da nicht viel. Bleib ruhig bei dem, wo Du gerade bist (oder gibt es etwas, was Dir hier fehlt?). Hast Du mit einer Komponente begonnen, solltest Du nicht wahllos nach Alternativen suchen. Das macht man i.d.R. vor dem Beginn eines Projekts Die machen aber in deinem Fall auch nichts leichter!

Zitat:
Wie kann ich alle aktiven Server im Netzwerk anzeigen lassen?
Sodass die Clients dann auch darauf connecten koennen!
Das kommt immer ganz auf das Netzwerk an. An sich gibt es immer zwei Möglichkeiten, einen zentralen und einen dezentralen Ansatz. Zentral bezieht sich dabei immer auf einen Server. Dieser hat eine Adresse (entweder statische IP oder halt ein DynDNS-Derivat, so dass der über den DNS-Eintrag immer gefunden wird). Jedes Spiel wird dann bei diesem Server angemeldet.
Hier ist es wichtig zu unterscheiden, der Server, an dem Du arbeitest, den nenne ich mal A. A ist für ein Spiel zuständig. Der zentrale Server heißt jetzt B. Nur B muss unter einem festen Namen erreichbar sein. Startest Du ein neues Spiel (erstellst also einen A), dann meldest Du Dein Spiel (Dein A) bei dem zentralen Server B an. Starte ich jetzt das Programm und möchte mich einem Spiel anschließen, so verbinde ich mich mit B (der ist ja bekannt). B zeigt mir dann alle Server (As) an, die momentan verfügbar sind. Da würde dann Dein A auftauchen. Verbinde ich mich mit dem, so kennt B halt die Adresse von A, gibt die mir und ich verbinde mich direkt mit Deinem A.
B vermittelt hier also nur und hostet nicht alle Spiele!

Die Alternative ist der dezentrale Ansatz. Dabei gibt es einfach keinen bekannten Server, was die Sache deutlich schwieriger macht! Für ein "privates" Netzwerk kannst Du einfach einen Broadcast machen. Dabei sendest Du einfach eine Anfrage an jeden Rechner im Netzwerk. Soweit die Infrastruktur das unterstützt, geht dies über eine spezielle Broadcast-Adresse, z.B. der X.X.X.255. Alternativ kann man hier auch von einem Multicast sprechen, aber ich denke die Funktionalität bleibt eher teueren Switches vorenthalten (hier geht die Anfrage an mehrere Rechner, aber nicht zwangsweise an alle).
Unterstützt der Switch keine Broadcasts, kannst Du natürlich einfach alle möglichen Adresesn durchgehen.
Für große Netze führt das schnell zu einer Menge (unerwünschten) Traffic. Für das sehr große Netz Internet funktioniert der Ansatz natürlich gar nicht (4,2 Mrd. Rechner abfragen wäre aber auch nicht all zu klug). Da hast Du dann keine einfache Möglichkeit. Natürlich gibt es P2P Clients, die dezentral arbeiten, diese nutzen aber ihre Verbreitung aus! Dort versucht man einfach zufällig auf ein paar (recht vielen) Adressen und einem bestimmten Port eine Anfrage. Findet man jmd. der dort antwortet (also auch das Programm verwendet), so tauscht man einfach die schon bekannten anderen Teilnehmer aus. Je mehr Leute also mitmachen, desto größer wird die Liste. Bei Deinem Programm dürfte das schwerer werden, dass Du zufällig jmd. findest, der das Programm auch verwendet, nun ja, eher unwahrscheinlich.
  Mit Zitat antworten Zitat