|
Antwort |
Registriert seit: 5. Dez 2006 459 Beiträge |
#31
Ok, aber er gibt immernoch ein Problem aus!
Und zwar: "Project LAN_Poker raised exception class EStackOverflow with message 'Stack overflow'" Ich werd daraus net schlau sorry (hoffe es ist nicht wieder son dummer Fehler)! |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#32
Zitat von .chicken:
Und zwar:
"Project LAN_Poker raised exception class EStackOverflow with message 'Stack overflow'" Der Stack ist dabei ein Speicher mit einer max. Größe. Legst Du also nur lang genug was darauf ab, gibt es einen Stackoverflow. Die Grenze ist dabei sehr hoch gesetzt, kommt es zu einem Stackoverflow, liegt das i.d.R. wirklich am Programm! Schau einfach mal, wo sich eine Prozedur selbst aufruft (oder Du sonst einen Kreis hast). Als Hilfe kannst Du einfach einen Breakpoint (diese roten Punkte/ F5) setzen. Dort hält Delphi dann an, wenn Du das Programm ausführst. Hier kannst Du nun mit F7 in die Ausführung reinspringen und siehst, was Dein Code gerade macht. Bei größeren Schleifen kann das nerven, hier kannst Du auch einfach auf die Zeile hinter die Schleife einen neuen Breakpoint setzen und mit F9 die Ausführung fortsetzen. Die geht normal weiter, bis das Programm endet, ein Fehler auftritt oder ein Breakpoint den Ablauf erneut unterbricht. |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#33
Yeeehaw soweit klappts
Super, vielen Dank und die Sache mit dem Breakpoint ist auch nicht schlecht zu wissen (Der Fehler war übrigens, dass ich den Konstruktor des Servers falsch deklariert hatte (ohne "AOwner: TComponent")) |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#34
Ok, also bisher geht alles ganz gut, bin grad bei dem Senden und Auswerten von Nachrichten!
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!
Delphi-Quellcode:
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!
type
TKarte = class FBild, FFarbe: Integer; FVerdeckt: Boolean; Private Public property Bild: Integer read FBild write FBild; //Bild der Karte property Farbe: Integer read FFarbe write FFarbe; //Farbe der Karte property Verdeckt: Boolean read FVerdeckt write FVerdeckt; //Status der Karte end; TSpieler = class FHand: Array [1..2] of TKarte; FFolded: Boolean; FGeld, FBet: Integer; procedure SetHand(Index: Integer; Value: TKarte); function GetHand(Index: Integer): TKarte; Private Public property Hand[Index: Integer]: TKarte read GetHand write SetHand; property Folded: Boolean read FFolded write FFolded; property Geld: Integer read FGeld write FGeld; property Bet: Integer read FBet write FBet; end; var Spieler: Array off TSpieler; PS: Ich hab die Units nochmal angehängt! Edit: Sollt ich mich vielleicht doch in die IndyKomponenten einarbeiten? Ist das damit einfacher zu realisieren? |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#35
Und ich hab noch eine Frage:
Wie kann ich alle aktiven Server im Netzwerk anzeigen lassen? Sodass die Clients dann auch darauf connecten koennen! |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#36
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! 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!
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:
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?
Zitat:
Wie kann ich alle aktiven Server im Netzwerk anzeigen lassen?
Sodass die Clients dann auch darauf connecten koennen! 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. |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#37
Ok, also erstmal ne Frage vorweg!
Hab im Inet was über ein Protokoll gelesen, dass die Kommunikation zwischen Server und Client regelt. Damit ist doch nichts anderes gemeint, als das auswerten von Textnachrichten, die zwischen Server und Clients hin und hergeschickt werden oder? Ok, dann zum Stand der Dinge Hab nun die Kommunikation zwischen Server und Client ziemlich fertig (das nötigste zumindest, hinterher wird das sicher noch erweitert). Jetzt habe ich aber ein neues Problem. In meiner Unit "Controller" habe ich die procedures "Call", "Bet", etc.! Die Unit "Server" hat den "Controller" in der uses Klausel! Jetzt muss aber der Server die Clients aktualisieren, wenn zB ein Call ausgeführt wird. Kann das dem Controller aber nicht sagen, weil der Server ja nicht in seinen uses steht! Gibts da ne Möglichkeit? "Über-Kreuz-uses" sollen (laut dem Forum) ja nicht gut sein (und funktioniern eh nicht!?). D.h. ich müsste Kommunikation zwischen Server und Controller umstrukturieren und den Server in die uses Klausel des Controllers schreiben, nicht umgekehrt? Oder geht das auch anders? Danke soweit! Edit: Ok, hab nun einfach den Controller ganz weggelassen und das ganze Zeugs direkt vom Server machen lassen! Klappt so super, ist natuerlich nurn bissl mehr Code im Server aber egal Wenn das Projekt fertig ist wirds eh nochmal komplett überarbeitet, wenn mir dann ne Lösung einfällt änder ichs vielleicht nochmal |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#38
Zitat von .chicken:
Hab im Inet was über ein Protokoll gelesen, dass die Kommunikation zwischen Server und Client regelt.
Damit ist doch nichts anderes gemeint, als das auswerten von Textnachrichten, die zwischen Server und Clients hin und hergeschickt werden oder? Um es einfach und kurz zu sagen, ein Protokoll legt nur fest, wie man kommuniziert. Es gibt zig Protokolle, die Du verwenden kannst, die Teilweise sogar auf einander aufbauen. Nimm einfach TCP/IP, dabei handelt es sich keineswegs um ein einziges Protokoll, vielmehr um TCP over IP. So steckst Du die Daten, die Du übertragen möchtest einfach in TCP-Pakete. Diese Pakete wiederum verpackst Du in IP-Pakete (dort stimmt der Begriff Paket nicht mehr ganz) und verschickst sie. IP stellt dabei nur sicher, dass irgendwelche Bytes an den Empfänger mit der angegebenen IP geht. Diese irgendwelchen Bytes werden auf der Empfängerseite dann weiter verwendet. Dort gibt es dann auch die IP Schicht, die diese Daten empfängt und an die darüberliegende Schicht weiterreicht. Für IP waren es nur irgendwelche Bytes, für die darüber liegende TCP Schicht ist es dann aber schon ein TCP-Paket. Das enthält ein paar Informationen (welches Paket um die Reihenfolge sicherzustellen, welche Checksumme um Übertragungsfehler zu erkennen...) und irgendwelche Nutzdaten (wieder nur Bytes). Für die darüber liegende Schicht gibt es z.B. auch wieder ein Protokoll, dass diese Nutzdaten bekommt und weiter verarbeitet. Deine Anwendung steht dabei auf der obersten Schicht (schau Dir einfach mal das OSI Modell an). Willst Du also Daten verschicken, läufst Du von oben nach unten und packst für jede Schicht (außer der physikalischen Übertragungschicht) einfach weitere Daten außen rum (die für die jeweilige Schicht benötigt werden). Auf jeder Schicht könntest Du dann von einem Server und einem Clienten sprechen (ziemlich allgemeine Begriffe). Natürlich kannst Du auch in Deiner Anwendung noch viele weitere Protokolle einbauen, die dann auf dem TCP/IP aufbauen. Auch auf jede dieser Schichten könnte dann zutreffen, dass die jeweils einen Client oder Server kennen. Wichtig ist eigentlich nur, dass für jede Schicht immer Metainformationen (nur für die Schicht wichtig!) und Nutzdaten übertragen werden. Die Nutzdaten interpretiert die Schicht dabei nicht weiter, sondern reicht diese an die nächst höhere Schicht weiter. Ganz oben steht immer etwas, dass nur noch Nutzdaten bekommt und mit denen Arbeitet. Bei einem Webserver hättest Du auch einen Interpreter, der eine HTML-Seite rendert. Die HTML-Seite wird dabei über das Hyper Text Transport Protocol (HTTP) übertragen. Dieses wird durch TCP-Pakete übertragen. Diese werden über IP übertragen.... Was für Nutzdaten in der obersten Schicht landen ist egal. Es sind einfach Bytes, die beliebig interpretiert werden können. Hast Du ein Datum von 4 Byte, kann das eine Zahl sein (z.B. ein Integer/Cardinal, ein Single, zwei Word, 4 Byte), es könnten Zeichen sein (4 Ascii Zeichen, 4 UTF-8 kodierte Zeichen, 2 UTF-16 kodierte Zeichen), aber auch alles andere, was in 4 Byte kodiert werden kann. Wie Du was überträgst kannst Du einfach in einem Protokoll festlegen (es sind also Nachrichten, aber nicht zwangsläufig Textnachrichten).
Zitat von .chicken:
In meiner Unit "Controller" habe ich die procedures "Call", "Bet", etc.!
Die Unit "Server" hat den "Controller" in der uses Klausel! Jetzt muss aber der Server die Clients aktualisieren, wenn zB ein Call ausgeführt wird. Kann das dem Controller aber nicht sagen, weil der Server ja nicht in seinen uses steht! So muss der eigentliche Auslöser den Server benachrichtigen, was getan wurde. Der Server wiederum muss alle Clients benachrichtigen. Bekommen die Clients eine Benachrichtigung vom Server, müssen sie diese darstellen. Das alles passiert, wenn ein Bet gemacht wurde, allerdings an drei völlig verschiedenen Stellen. Für alles könnte ein Controller in Frage kommen, der eine Methode "bet" hat (der Name "Bet" ist imho hier zu aussagelos).
Zitat von .chicken:
Gibts da ne Möglichkeit? "Über-Kreuz-uses" sollen (laut dem Forum) ja nicht gut sein (und funktioniern eh nicht!?).
Es gibt immer saubere Alternativen (es geht also immer auch anders)! Der einfachste Weg ist es immer, dass Du die Units neu aufteilst. Häufig reicht es schon, dass man einen Teil in eine dritte Unit schiebt, auf die die beiden anderen zugreifen können. Diese dritte Unit sieht aber dafür die anderen zwei nicht. In diesem Fall musst Du nur schauen, was alles passieren kann und wer dazu welche Informationen benötigt. Betrachte ich die Methode Bet, so würde ich sagen, dass die immer dann aufgerufen wird, wenn jmd. etwas setzt. Da würde es mich dann aber stark wundern, dass der Server diese Methode / Unit kennen muss, denn der Server selbst wird nur benachrichtigt, wenn diese Methode von einem der Spieler aufgerufen wurde (wenn der selber setzt wäre das doch ungewöhlich). Aber auch den umgekehrten Weg würde ich nicht ganz verstehen, setzt ein Spieler, so würde hier die Methode Bet aufgerufen werden. Diese Methode wird also Clientseitig aufgerufen. Ein Client muss die Server-Unit gar nicht kennen, sondern sendet über einen TCP-Client eine Nachricht an den Server. Hier muss also die Unit Controller nur eine Möglichkeit haben, die Nachricht zu verschicken (oder jmd. zu informieren, was gemacht wurde, so dass dieser jmd. die Nachricht verschickt). Kommt die Nachricht beim Server an, so muss der alle Clienten darüber Informieren, was eine eigene Methode ist. Dabei muss der Server seine Liste der gemeldeten TCP-Clienten durchgehen und ihnen eine Nachricht zuschicken. Hier ist nur wichtig, dass über TCP (oder welche Protokoll auch immer) eine Nachricht versendet wird. Empfängt jetzt ein Client eine Nachricht, so muss er eine Ereignisbehandlung durchführen. Auch hier sehe ich nicht, dass ein Zugriff auf den Controller nötig wäre. Wo also siehst Du das Kreuz? Deutlicher gesagt würde ich folgenden Ablauf sehen/modellieren:
Die Namen sind jetzt nicht sonderlich gut gewählt, es soll nur anzeigen, dass hier nirgendwo ein Kreis entsteht, ein Überkreuzen ist also nicht nötig (soweit ich nicht irgendwas übersehe).
Zitat von .chicken:
Edit: Ok, hab nun einfach den Controller ganz weggelassen und das ganze Zeugs direkt vom Server machen lassen! Klappt so super, ist natuerlich nurn bissl mehr Code im Server aber egal
Gehst Du aber immer den Weg, den Du gerade gegangen bist, dann führt das einfach zu riesigen Units. Die sind sehr viel schlechter wartbar und fehleranfälliger. Möchtest Du eine bestimmte Funktionalität wiederverwenden, so wird Dir schnell die gesamte Unit zu groß sein und man neigt zu copy&paste, bei so großen Units kannst Du dabei schnell mal eine wichtige Abhängigkeit (von etwas anderem in der Unit) übersehen und Du kopierst etwas, dass zwar kompiliert aber totaler Mist ist! Deswegen lieber kleine Units, die eine kleine Aufgabe lösen.
Zitat von .chicken:
Wenn das Projekt fertig ist wirds eh nochmal komplett überarbeitet, wenn mir dann ne Lösung einfällt änder ichs vielleicht nochmal
Hast Du gleich sauber gearbeitet, stellt das spätere Anpassen (soweit es überhaupt nötig wird) kein Problem dar. Und glaub mir, dass ist kein erfundenes und übertriebenes Worst-Case-Szenario, sondern so ging es mir damals wirklich regelmässig. Da findet man nicht mal ebend eine Stelle, die man leicht ändern kann! Häufig passiert sowas zudem aus Zeitdruck heraus. Gibt man dem Druck nach, bekommt man vielleicht noch irgendwas zusammen, das läuft, aber der Nachfolgeauftrag ist dann schon nicht mehr wünschenswert! Da sollen dann eben kleine Änderungen vorgenommen werden, irgendwas Neues rein und Du stehst vor irgendeinem Chaos, dass Du irgendwann mal überarbeiten wolltest und weißt nicht wo anfangen. Damit erhöht sich nur der Aufwand, für das, was Du in der gleichen Zeit packen musst... Deshalb gilt wirklich, mache alles gleich richtig! Da gibt es diese bekannte Rechnung, dass eine Problem/Fehler während der Planung grob einen Dollar kostet (jeweils um behoben zu werden!), während der Implementierung der Funtion kostet der gleiche Fehler schon 10 Dollar, nach Fertigstellung/Zusammensetzen der Software kostet er 100 Dollar und wenn das Produkt ausgeliefert wurde > 1000 Dollar. Die Zahlen sind hier natürlich symbolisch zu verstehen, lieferst Du ein schlechtes Produkt aus, kann es Dich auch alles kosten (Imageschäden kann man nicht mit Geld beziffern). Trotzdem stimmen die Relationen der Kosten schon ganz gut, man hat echt schnell eine Verzehnfachung des Aufwands (gefühlt noch viel mehr), wenn man etwas vor sich her schiebt. Das gilt auch für Dinge, die man zu einem bestimmten Zeitpunkt noch nicht berücksichtigt. Je früher man etwas mit einbezieht, desto besser!!!! |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#39
Ok, wahrscheinlich hast du Recht und ihc bin auch shcon ziemlich durcheinander im Projekt. Das liegt einfach daran, dass am Anfang viele Dinge nicht mit bedacht werden und die dann hinterher füchtig eingesetzt werden!
Ich denke ich schriebe die Units nochmal neu und ordentlich! 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! Ich weiss nun wie ich über-kreuz-uses machen kann, aber ich will es garnicht, will mein Projekt ja hinterher ordentlich haben! Was hälst du denn davon wie ich die Nachrichten schicke und auswerte? Ich schreib hier ma n paar Zeilen dazu:
Delphi-Quellcode:
Ansatz so richtig oder Verbesserungsvorschlag?
SendText('Call'); //wär zB ein einfacher Call
SendText('SGeld(1)[1500]'); //würde zB das Geld von Spieler 1 auf 1500 setzen 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. Sieht dann zB so aus:
Delphi-Quellcode:
Gibts da eigentlich ne schönere/bessere Möglichkeit als diese tausend if-Abfragen?
function TMyClient.Klammern(Value, Search1, Search2: String): String; //eben genannte Funktion
begin Result := Copy(Value, Pos(Search1, Value) + 1, Pos(Search2, Value) - Pos(Search1, Value) - 1); end; procedure TMyClient.Parse_Text(Value: String); //hier wird dann der Text ausgewertet, hoffe das ist einigermassen verständlich! var temp: String; begin temp := Copy(Value, 0, Pos('[', Value) - 1); if temp = 'CBet' then //CBet wird geändert CBet := StrtoInt(Klammern(Value, '[', ']')); if temp = 'Phase' then //Phase wird geändert Phase := StrtoInt(Klammern(Value, '[', ']')); if temp = 'SBlind' then //SBlind wird geändert SBlind := StrtoInt(Klammern(Value, '[', ']')); if temp = 'Dealer' then //Dealer wird geändert Dealer := StrtoInt(Klammern(Value, '[', ']')); if temp = 'AktiverSp' then //AktiverSp wird geändert AktiverSp := StrtoInt(Klammern(Value, '[', ']')); if temp = 'Pot' then //Pot wird geändert Pot := StrtoInt(Klammern(Value, '[', ']')); if temp = 'ClientNumber' then //ClientNr wird zugewiesen ClientNr := StrtoInt(Klammern(Value, '[', ']')); if temp = 'Start' then //Spielstatus if Klammern(Value, '[', ']') = 'True' then Start := True else Start := False; end; Und dann hab ich da noch ein Problem: Der Server schickt oft soviele Nachrichten nacheinander, dass der Server beim auswerten die Nachrichten durcheinander bringt, wie kann ich das verhindern? Danke für die Hilfe und hoffe ich hab nix vergessen, aber jetzt muss mein Hund raus |
Zitat |
Registriert seit: 1. Apr 2005 Ort: Bad Tölz 4.149 Beiträge Delphi 2006 Professional |
#40
Hallo,
ich würde das nicht per Text machen.
Delphi-Quellcode:
Das geht schneller auszuwerten und ist weniger tippfehleranfällig.
type
TPlayerActionType = (atBet, atCall, atCheck); TPlayerAction = packed record TimeStamp: TDateTime; ActionType: TActionType; Current: Cardinal; end;
Lukas Erlacher
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |