AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Pokerprojekt realisierung
Thema durchsuchen
Ansicht
Themen-Optionen

Pokerprojekt realisierung

Ein Thema von .chicken · begonnen am 28. Mär 2007 · letzter Beitrag vom 15. Mai 2007
Antwort Antwort
Seite 5 von 7   « Erste     345 67      
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#41

Re: Pokerprojekt realisierung

  Alt 7. Apr 2007, 20:39
Hm danke für die Antwort aber habe im Delphi-Forum gelesen, dass das nicht gut ist records zu verschicken und man sich lieber die Mühe machen sollte eine ordentliche Auswertung für den Text zu schreiben!?
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#42

Re: Pokerprojekt realisierung

  Alt 7. Apr 2007, 20:41
Link bitte...

Was heißt da "ordentlche Auswertung". Fakt ist, Strings matchen ist für sowas total falsch(weil langsam und fehleranfällig), es sei denn, man will es z.B. für Menchen lesbar halten.
Lukas Erlacher
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#43

Re: Pokerprojekt realisierung

  Alt 7. Apr 2007, 20:55
So kurz bissl gesucht
http://www.delphi-forum.de/viewtopic...ighlight=split

Edit: Da stand übrigens auch das mit dem Protokoll, genauer Kommunikationsprotokoll!
  Mit Zitat antworten Zitat
Der_Unwissende

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

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 12:05
Zitat von DGL-luke:
Was heißt da "ordentlche Auswertung". Fakt ist, Strings matchen ist für sowas total falsch(weil langsam und fehleranfällig), es sei denn, man will es z.B. für Menchen lesbar halten.
Das stimmt doch so schon nicht. Sorry, aber wie kommst Du denn darauf?! Nimm einfach mal XML, ist natürlich langsam, aber keineswegs fehleranfällig oder nur für den Menschen lesbar gehalten. Der eigentliche Hauptvorteil von Strings liegt darin, dass diese immer gleich sind (unabhängig von Byteorder, Feld-Ausrichtung, ...). Klar, auch dort muss man einiges im Protokoll festlegen, aber Du hast eine sehr viel einfachere Erweiterbarkeit (Schlußzeichen), beliebige Anordnung der Bestandteile und kannst sehr einfach Programmiersprachen übergreifend damit arbeiten.
Records mögen schneller sein, sind aber eben für schlechter durch einen Menschen lesbar, auf eine feste Anordnung und Byteorder ausgerichtet und sehr viel schlechter zu erweitern. Natürlich kann man einfach die Größe eines Records senden, bevor das Record übertragen wird, aber die Kommunikationspartner sollten schon wissen, was sich wo in dem Record befindet.
Um das zu umgehen, verwendet man dann in der Regel Auszeichnungen (Tags) und hat ruck-zuck nichts anderes als ein Protokoll, dass eben auch durch Strings realisiert werden kann. Gute Beispiele für die Mächtigkeit sind so flexible Formate wie z.B. Tiffs oder auch XML-Dateien.

Zitat von .chicken:
Zu der Sache mit dem Controller. Also nur der Server kennt den Controller!
Wenn ein Spieler setzt, schickt er eine Nachricht an den Server, zB:
'Bet[600]' ---> 600setzen
Wenn der Server das empfängt, soll er den Controller benachrichtigen, dass er die procedure Bet aufruft!
Dann kann der Controller aber nichtmehr den Server benachrichtigen, wenn er die procedure ausgeführt hat, weil er den Server ja nicht in den Uses hat!
Nochmal dazu, ich verstehe Deinen Ansatz nicht. Warum muss der Controller den die Server Unit kennen? Die Serverunit kapselt doch nur einen TCP-Server (um die Komponente von der Unit zu trennen). Der TCP-Server lauscht in Deinem Programm auf einem Port auf dem Rechner. Kommt eine Anfrage, macht er irgendwas.
Auf der anderen Seite gibt es noch den Clienten. Der besteht unter Anderem aus einem Controller, aber auch aus dem TCP-Client, der mit dem TCP-Server verbunden ist (nach Beitritt zum Spiel) und Nachrichten abschicken kann.
Der Spieler wiederum sitzt vor dem Formular/GUI und drückt einen Knopf. Der Knopf repräsentiert jetzt ein Call, das wird dem Controller mitgeteilt. Der Controller muss das nun an den Server (hier ist der Rechner gemeint, der das Spiel hostet) weiterleiten. Dazu greift der Controller auf seinen eigenen TCP-Client (eigen im Sinne von einges Programm) zurück und schickt die Nachricht ab. Da der TCP-Client mit dem richtigen Rechner verbunden ist, kommt die Nachricht an und hier nimmt sie der TCP-Server entgegen.
Warum muss hier der Controller den Server kennen?

Zitat von .chicken:
Was hälst du denn davon wie ich die Nachrichten schicke und auswerte?
Was ich hier bemängeln würde ist, dass Du wirklich das Problem von Schreibfehlern haben könntest. Du solltest lieber eine Datei anlegen, die alle Kommandos als Konstanten enthält.
Delphi-Quellcode:
CONST COMMAND_CALL = 'Call';
      ...

SendText(COMMAND_CALL);
Damit kannst Du die Strings leicht an einer Stelle ändern (ohne dass Du eine Stelle übersiehst). Sonst kommt es vielleicht dazu, dass Du mal 'Call' mit 'call' vergleichst und das wird wohl nie gleich sein. Es ist einfach sicherer hier mit Konstanten zu arbeiten!

Zitat von .chicken:
Zur Auswertung hab ich mir ne Funktion geschrieben, der ich einen String und zwei Zeichen geben kann, und die dann den Substring zwischen den beiden Zeichen ausgibt
Finde ich gut!

Zitat von .chicken:
Gibts da eigentlich ne schönere/bessere Möglichkeit als diese tausend if-Abfragen?
Nein, die gibt es nicht. Der andere Ansatz besteht darin, dass Du wirklich feste Datensätze (Größe und Struktur ist statisch) überträgst. Da ist dann aber alles mögliche festgelegt und das ist eher weniger zu empfehlen. Heutige Rechner haben einfach massenhaft Leistung. Dynamik dominiert deutlich den Wunsch nach mehr Perfomance (die kommt eh ständig dazu). Modernere Formate (hatte ja vorhing schon Tiff und XML als Beispiel genannt, aber auch MS designierter Bitmap Nachfolger, PDF, ...) setzen auf Auszeichnungen, die zwar geringe Perfomancenachteile mit sich bringen, aber bei denen offensichtlich der Wunsch nach Flexibilität und Erweiterbarkeit doch deutlich im Mittelpunkt steht.
An sich solltest Du aber mit if ... else arbeiten. Ein else wird dabei nur ausgewertet, wenn das vorhergehende if als nicht wahr ausgewertet wurde. So wie Du es jetzt machst, könnte das erste If bereits zutreffen, es würden trotzdem auch alle anderen Punkte ausgewertet werden.

Zitat von .chicken:
Der Server schickt oft soviele Nachrichten nacheinander, dass der Server beim auswerten die Nachrichten durcheinander bringt, wie kann ich das verhindern?
Was genau kommt denn da durcheinander?
Ich schätze einfach mal, dass Du mit einer globalen Variable arbeitest, in die Du das einliest, was der Server empfängt/verschickt. Wechsel hier einfach auf eine lokale Variable, dass sollte das Problem schon beheben.
Hast Du das Problem, dass die Daten als Kette im Speicher landen (also z.B. 'CallBet...Call') und Du nicht weißt wo ein Datum anfängt und das andere endet (sollte bei TCP eigentlich nicht der Fall sein), dann könntest Du einfache Start- und Endzeichen vor jede Nachricht setzen und den String anhand dieser zerlegen (also z.B. 'Call#Bet....#Call').
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#45

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 12:54
Also die Idee mit den Konstanten find ich gut, das einzige was ich dabei noch nich ganz verstehe:
Ich habe ja variable Parameter in manchen Nachrichten ('Bet[600'] zB), wie setz ich das um?

Dann hab ich im Anhang mal ne kleine Grafik wie ich es jetzt geplant habe, um der Sache mit Controller und Server zu entgehen (vielleicht verdeutlicht das auch wie die Dinge in Verbindung stehn )

Dazu ne Erklärung!
-> Benutzer klickt auf Bet600
-> Client wird informiert, dass er die Infos zum Server schickt ('Bet[600]')
-> Server empfängt Nachricht im onClientRead-Event
-> Server gibt dem Connector die Aufgabe den Controller zu benachrichtigen die Aktion Bet600 auszuführen
-> Connector benachrichtigt den Controller
-> Controller führt Bet600 aus und am Ende der prozedur gibt er dem Server bescheid, die Clients zu aktualisieren
-> Server schickt Nachrichten
-> Client wertet sie aus und gibt über den anderen Connector der Benutzeroberfläche Bescheid dass sie aktualisiert werden muss
So würde es dann immer weiter gehn. Also hab mir da einige Gedanken zu gemacht und denke das is der simpelste Weg!?
Vielleicht hab ich aber auch einfach n Brett vorm Kopf und komm auf die viel einfachere Idee nicht!


Zu dem durcheinander Kommen der Nachrichten. Hab mir die mal per Showmessage ausgeben lassen, während der Server grade alle Infos des Clients aktualisiert, dh. es werden viele Nachrichten kurz nacheinander geschickt (mit Infos wie 'was ist momentan gesetz', alle in unterschiedlichen Nachrichten).
Die hab ich dann im onRead Event des Clients in die Variable 'Text' schreiben lassen und wollte sie mir dann ausgeben.
Aber statt das er nur zB 'CBet[600]' ausgibt, kommt er total durcheinander und schreibt zB 'CBet[600]AktuellerSpieler[3]'.


So das wars erstma wieder von mir, danke für die ausführliche Antwort!

Edit: Einfach mal Anhang vergessen

Edit2: Ach noch eine Frage. Kann ich bei einem Client irgendwie rauskriegen welche "Nummer" seine Verbindung hat? Also der Server schickt ja zB Nachrichten per Socket.Connections[i].SendText.
Wie krieg ich raus was das "i" eines Clients ist?

Hab bisher immer wenn ein Client connected hat vom Server eine Nachricht mit den aktiven Verbindungen (-1) geschickt (musste dann ja seine sein weil er als letztes connected hat).
Geht aber doch sicher auch einfacher?
Angehängte Grafiken
Dateityp: bmp serverclient_176.bmp (351,6 KB, 16x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#46

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 19:20
Zitat von Der_Unwissende:
Das stimmt doch so schon nicht. Sorry, aber wie kommst Du denn darauf?! Nimm einfach mal XML, ist natürlich langsam, aber keineswegs fehleranfällig oder nur für den Menschen lesbar gehalten.
Natürlich ist es fehleranfällig - einmal vertippt und feddisch. da sagt dir jeder XML-Parser: nicht wohlgeformt, weg damit.

Also, nochmal:

Strings
- fehleranfällig (tippfehler, unterschieldiche encodings)
- langsam
- menschlich lesbar
- redundant

Records
- nicht so fehleranfällig (wenn man sich bei einem enum vertippt meckert der compiler - wenn man sich beim string-protokoll vertippt, kreigst du ne wunderschöne exe, die aber hinten und vorne nicht funktioniert)
- nicht menschlich verarbeitbar (bis auf leute, die auch per ASM programmieren )

Können wir uns darauf einigen? Und ansonsten bitte im DF weiter, ich kämpf doch hier kein zweifrontenkrieg...
Lukas Erlacher
  Mit Zitat antworten Zitat
Der_Unwissende

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

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 19:33
Zitat von DGL-luke:
Können wir uns darauf einigen? Und ansonsten bitte im DF weiter, ich kämpf doch hier kein zweifrontenkrieg...
Keine Sorge, ich möchte keinen Krieg führen, fände es aber etwas schade hier nur die Nachteile zu betrachten. Es geht (für mich) auch gar nicht um die Diskussion String vs. Record, sondern Auszeichnung (dyn. Struktur) vs. Record (statische Struktur). Meinetwegen kann man auch das Tiff-Format missbrauchen (muss kein String drin vorkommen) und ein Format erstellen, dass diesem ähnelt (hat MS ja z.B. für ihr Photoirgendwas-Format gemacht, eben den designierten Bitmap Nachfolger).

Ich stimme Dir aber zu (womit sich hoffentlich ein Krieg vermeiden lässt ), dass reine Strings auch fehleranfällig sind. Verschicke ich allerdings aus eine Version a ein Record über einen Kanal an eine Version b, habe ich das gleiche Problem, die kompilieren super, aber ich muss auch auf beiden Seiten die gleiche Version haben. Dyn. Struktur setzt das nicht vorraus, erfordert aber mehr Aufwand.
Für Beide Fälle gibt es Möglichkeiten die negativen Effekte zu minimieren. Das ganze ist aber sicherlich etwas mehr ein Thema für sich (das DF?), als dass es hier auch noch diskuttiert werden kann/muss/braucht/whatever, oder?
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#48

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 19:36
Kein Problem. Ich glaube auch nicht, dass wir hier aus der Frage "Stringprotokoll/Binärprotokoll" einen Glaubenskrieg anfachen müssen.

Hat beides seine Berechtigung. Und wie gesagt: weiter dann im DF.
Lukas Erlacher
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#49

Re: Pokerprojekt realisierung

  Alt 8. Apr 2007, 19:46
Und was is zu meiner Frage? (siehe Seite 3)

Edit: Wobei mir grad auffällt, das meine Methode so garnicht richtig funktioniert glaub ich!

Kann ich die uses nicht wie folgt anordnen?
[delphi]
Server
uses
Connector

Connector
uses
Controller

Controller
uses
Server
[*delphi]
So hätte ich ja sone Art Dreieck, sodass jeder mit jedem kommunizieren kann, aber er spuckt mir da immer den Fehler aus, dass ich falsche uses hab!

Edit2: Also hab ein sehr gutes Tutorial zum Kommunikations-Protokoll gefunden und arbeite das grade durch und dabei is mir nochmal n Licht aufgegangen, wie ich alles viel simpler lösen kann
Dh ich arbeite nun erstmal an dem neuen Lösungsweg und wenn weitere Fragen auftreten melde ihc mich
Danke soweit
  Mit Zitat antworten Zitat
Der_Unwissende

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

Re: Pokerprojekt realisierung

  Alt 9. Apr 2007, 12:19
Zitat von .chicken:
Kann ich die uses nicht wie folgt anordnen?
[delphi]
Server
uses
Connector

Connector
uses
Controller

Controller
uses
Server
[*delphi]
Ich glaube das Du da immer noch einen totalen Denkfehler drin hast. Du musst den Server komplett getrennt vom Client betrachten. Stell Dir einfach vor, Du hättest hier wirklich zwei Programme laufen. Bei vielen Client/Server Anwendungen ist das ja der Fall (Google läuft auf einem Webserver, auf einem Cluster, Dein Webbrowser wohl eher auf Deinem Rechner).
Die beiden Programme kommunizieren über einen bestimmten Kanal. Wie sie dabei Daten austauschen legt das Protokoll fest.

Ich hab die Idee noch mal grafisch aufbereitet (nicht all zu hübsch, aber vielleicht trotzdem leichter verständlich). Schau einfach mal in das angehängte PDF.
Auf der ersten Seite findest Du dann den Ablauf, wie es grob aussehen könnte, wenn ein Spieler eine Aktion ausführt. Es beginnt bei der GUI, wo der Benutzer irgendwas macht (z.B. einen Button anklickt). Das ganze ist ein Ereignis, wird behandelt und dem "Client Game Controller" mitgeteilt. Dieser Name mag etwas verwirrend sein und ist natürlich nicht bindend, es geht hier nur darum, dass man die einzelnen Teile gut unterscheiden kann.
Der "Client Game Controller" hat eine einfache Aufgabe, man teilt ihm mit, was gemacht wurde (irgendwie kommt das von der GUI rein). Er wandelt das dann in ein Format um, dass direkt übertragen werden kann (entspricht dem Protokoll, dass dein Server verwendet). Ich sag hier einfach mal (o.B.d.A.) es sein ein String. Dieser String wird dann an eine Komponente weitergereicht, die mit dem Server verbunden ist (der TCP-Client). Dieser verschickt (ohne weitere Logik) einfach einen String und gut ist.

Das ist auch alles, was auf Seiten des Clients soweit passiert. Weiter geht es auf der anderen Seite, dem Server. Hier wird vom TCP-Server eine eingehende Anfrage empfangen. Die wird er lesen und (hoffentlich) das Protokoll kennen. Diese Anfrage reicht der TCP-Server einfach weiter an den "Server Game Controller". Dieser wandelt den empfangenen String einfach in eine Änderung des Zustands um. Diese Änderung wir nun am "Game Server" vorgenommen. Der Name hier ist sehr schlecht gewählt, mir fällt aber kein guter ein. Mit Game-Server meine ich den kompletten Zustand des Spiels und Methoden diesen zu verändern. Wird der Zustand verändert, muss dies zu einer Benachrichtigung aller Clienten führen, das alles steckt schon in diesem Game-Server drin. Natürlich soll der dabei gar nicht eine eigenständige Komponente sein, hier gehe ich nur nicht näher ins Detail!

Ja, soweit war es das auch schon. Jetzt wurde der Zustand im Server geändert. Was wie gesagt implizit passieren muss, sobald sich ein solcher Zustand ändert ist, dass der Server allen Clients diese Änderungen mitteilt. Das siehst Du dann auf der zweiten Seite des PDF.
Hier spricht der Server einen "Update Controller" an. Auch dieser Name ist wohl etwas schlecht gewählt. Die Aufgabe dieser Komponente ist aber wieder leicht. Sie bekommt ein Änderungsereignis vom Server mitgeteilt und wandelt diese Änderung in einen String, der übertragen werden kann. Für jeden bekannten Client passieren die folgenden Schritte (auch wenn hier nur einer angezeigt wird).
Wurde der String erzeugt, wird der einfach an den TCP-Server gereicht*, der diesen String an die Zieladresse verschickt.
Auf Seiten des Servers war es das schon. Auf der anderen Seite wird nun der String vom TCP-Client empfangen* und an den "Client GUI Controller" weiter gereicht. Dieser macht eigentlich nichts anderes als das empfangene Ereignis darzustellen. Dazu parst dieser Controller einfach das Ereignis/den String und sagt der GUI, was sie anzeigen soll.

Das ist auch schon alles. Wie Du siehst, gibt es hier gleich 8 dargestellte Komponenten, was aber nur viel wirkt. Das eigentlich wichtige sind die Pfeile und ihre Richtung. Die wichtigste Sonderrolle nimmt die Linie ein, die durch das Netzwerk geht. Da sie durch das Netzwerk geht, soll sie wirklich eine TCP/IP Verbindung darstellen und muss gesondert betrachtet werden.
Die anderen Pfeile zeigen an, wer wen kennen muss. So greift das GUI auf die "Client Game Controller" Komponente zu, aber nicht umgekehrt. Diese wiederum verwendet den TCP-Client, aber nicht umgekehrt. Der ist über diesen gesonderten Kanal mit einem Server verbunden. Geh einfach die anderen Pfeile durch und Du siehst, dass sich hier keine zwei Komponenten gegenseitig kennen müssen.

Natürlich kannst Du jetzt sagen, dass das für Server und Client gilt, aber hier kommt wie gesagt ein gesonderter Kanal zum Einsatz. Dabei kennt der TCP-Client nicht wirklich den Server und umgekehrt, es sind nur die IP-Adressen und Ports des jeweiligen anderen bekannt, die Units müssen sich hingegen nicht kennen!
Vielleicht ist es ein guter Anfang, wenn Du die beiden Programmteile erstmal so entwickelst, dass Du doch erst einen getrennten, unabhängigen Server hast. Dann kann man Dir später helfen, wie Du den ins normale Spiel integrierst. Dabei solltest Du schon darauf achten, dass Du keine zwei Units in den beiden Programmen gleich nennst. So ist sicherlich auf beiden Seiten mindestens ein Controller zu finden, sie haben jedoch komplett unterschiedliche Aufgaben (der eine hat nur mit der Client, der andere nur mit der Server Seite zu tun). Gibt es Units die auf beiden Seiten bebraucht werden (die z.B. Konstanten enthalten oder Datentypen,...), dann pack die einfach in einen getrennten Ordner und füge sie beiden Projekten hinzu (Gelber Ordner mit grünem Plus oder unter Projekt -> Hinzufügen, denke ich). Dann kannst Du die gleiche Unit in beiden Teilen verwenden. Die Datei kopieren wäre hingegen ganz schlecht, hier könnte es schnell zu Update-Anomalien kommen.
Angehängte Dateien
Dateityp: pdf clientserver_104.pdf (37,5 KB, 16x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 5 von 7   « Erste     345 67      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz