Autor Beitrag
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 15.09.11 23:30 
Moin!

user profile iconDaniel775 hat folgendes geschrieben Zum zitierten Posting springen:
Da wird es hapern. Ich hab mir die .add Procedure mal angesehen. Ich kann da kein Objekt übergeben, oder? Wie kann ich da ansetzen?
Der "Witz" an dem TCmdSeq-Objekt ist ja, dass es keine strukturierten Daten annimmt, sondern immer nur einfache Datentypen. Kennst du die Methode und das Konzept von TPersistent.Assign() und .AssignTo()? Hier ist das genau so: in der Methode, die das Objekt übergeben soll gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt. Das ist die einzige Möglichkeit bei einer Änderung des Objekts keinen Datenmatsch zu produzieren. Ändert sich das Objekt, muss auch ein entsprechend geändertes Transport-Verfahren benutzt werden (hier: ein anderes Token).

Alternative wäre die Delphi-eigene Methode zum De-/Serialisieren von Objekte, so wie es die VCL/IDE mit den Komponenten tut. Ist aber bischen frickelig. :?

Noch ein anderer Ansatz ist die Transformation in das INI-Format, dieses als Text transportieren und auf der anderen Seite wieder aus dem INI-Format lesen.

Du merkst schon, egal was man macht, wenn man einfach nur "auf der einen Seite rein und auf der anderen genau so wieder raus" haben will, geht das gar nicht so einfach... jedenfalls nicht, wenn es "sauber" sein soll. :nixweiss:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Daniel775
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Fr 16.09.11 13:38 
Zitat:
...gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt.


Das heisst Praktisch für jede Eigenschaft in meinem Objekt ein neues Token und wenn sich die Eigenschaft oder das Objekt verändert diesse Änderung wieder über die Methode an das TCmdSeq-Objekt schicken. Hab ich das richtig verstanden?

Ich mache das im Moment mit einer .ini Datei. Und suche jetzt eine Client <> Server Lösung. Das würde bedeuten, das auch das Terminatorzeichen Protokoll für diese Aufgabe völlig ausreichend wäre!?
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 16.09.11 13:59 
Moin!

user profile iconDaniel775 hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
...gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt.
Das heisst Praktisch für jede Eigenschaft in meinem Objekt ein neues Token und wenn sich die Eigenschaft oder das Objekt verändert diesse Änderung wieder über die Methode an das TCmdSeq-Objekt schicken. Hab ich das richtig verstanden?
Ähm, nein. :? Machen wir mal ein Beispiel:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
type
  TSettings = class(TObject)
  private
    FStr: String;
    FInt: Integer;
  public
    function AsCmdSeq: TCmdSeq;
    property Str: String read FStr write FStr;
    property Int: Integer read FInt write FInt;
  end;

  TForm1 = class(TForm)
    NBFPAClient1: TNBFPAClient;
    NBFPAServer1: TNBFPAServer;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure NBFPAServer1ClientExecute(Sender: TObject; PA: TProtocolAdapter);
  public
    Settings: TSettings;
  end;

implementation

function TSettings.AsCmdSeq: TCmdSeq;
begin
  Result := TCmdSeq.Create(123); // das hier ist die Version 123 der Einstellungen
  Result.Add(FStr); // Eigenschaften schreiben
  Result.Add(FInt);
  //...
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  NBFPAClient1.SendAndFree(Settings.AsCmdSeq);
end;

procedure TForm1.NBFPAServer1ClientExecute(Sender: TObject; PA: TProtocolAdapter);
begin
  case PA.CurrentToken of
    123// Einstellungen in Version 123 angekommen
      begin
        Settings.Str := PA.Inbound.Strings[1]; // in der gleichen Reihenfolge wieder zuweisen
        Settings.Int := PA.Inbound.AsInt[2]; // wie geschrieben wurde
        //...
      end;
    122// Einstellungen in Version 122 angekommen (veraltet)
      begin
        Settings.Str := PA.Inbound.Strings[1]; // hier gabs nur den String, der Int war noch nicht bekannt
        //...
      end;
  end;
end;


user profile iconDaniel775 hat folgendes geschrieben Zum zitierten Posting springen:
Ich mache das im Moment mit einer .ini Datei. Und suche jetzt eine Client <> Server Lösung. Das würde bedeuten, das auch das Terminatorzeichen Protokoll für diese Aufgabe völlig ausreichend wäre!?
Jedes Protokoll ist für die Übertragung geeignet, egal welches. Damit wird ja nur Transportiert. Wie du die Einstellungen verwaltest, also als Objekt, Record, INI-Text, etc. ist doch davon unabhängig. :nixweiss:
Um die Frage zu beantworten: ja, das Terminatorzeichen-Protokoll wäre dafür auch ausreichend. ;)

Machen wir das mal anders: was soll das denn werden und worauf legst du Wert bei der Sache? :lupe:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.

Für diesen Beitrag haben gedankt: Daniel775
Daniel775
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Fr 16.09.11 20:20 
Zitat:

Machen wir das mal anders: was soll das denn werden und worauf legst du Wert bei der Sache?


Mein aktuelles Projekt ist eine Datenbankgestützte Zeiterfassung. Oder einfach gesagt, eine Stempeluhr. Mit Mitarbeiter, Urlaubs -und Fehlzeitenverwaltung. Es gibt ein UserFront-End als eigenständiges Programm wo halt eingestempelt wird und ein Admintool. Das Admintool möchte ich halt mit gewissen Funktionen ausstatten.
Wartungsmodus ein/aus, Anzeigedauer der letzten Einstempelungen usw.
Diese möchte ich mittels Client/Serververbindung an die Stempeluhr schicken. In Form einer Datei die dann beim start immer eingelesen wird. Dein Beispiel wird mir sehr helfen das umzusetzen .... vielen lieben Dank. :D
Das mit den Versionen in der ClientExecute Procedure gefällt mir und ist ein sehr guter Tipp.

Grüße
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Di 06.03.12 00:13 
Hallo,

ich baue momentan ein RPC-Interface rund um NBFPA. Das ganze läuft so ab, dass man dann z.B. ein OnEntityCall-Event bekommt, mit den Parametern: (Connection, EntityRef, Function, Parameter). Die kann man dann in Anwendungs-Code weiterverteilen an die richtigen Handler.
Das Problem ist jetzt, die Parameter richtig zu zerpflücken. Wenn ich einfach nur die TInboundFrameList übergebe, ist das unhandlich, da ja die ersten paar Argumente "intern" sind: Entity,FunctionCode etc.

Einfach die verarbeiteten ArgumentFrames aus der Liste löschen (damit die Paremter vorwandern) geht nicht, das kollidiert mit der NBFPA-Internen Verarbeitung. Ich würde die also gerne vorher zerpflücken und eventuell in ein Array of Const oder Variant reinschieben. Das ist an sich auch okay, aber die Überdeckung der damit darstellbaren Datentypen zu den mit NBFPA übertragbaren Formate ist gelinde gesagt gering. Selbst mit Auto-Konvertierung (Datentypen kann man ja mitsenden) wird das entweder nicht einfach oder bandbreitentechnisch eher schlecht.

Hat mit sowas jemand Erfahrung? Ich bin auch für Alternativkonzepte immer offen. Alles, was im Endeffekt einfach zu verwenden ist.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 07.03.12 00:54 
Moin!

An einem Stück Dispatcher-Code im OnExecute oder einer auf´s Nötige reduzierten Kopie der Parameter aus der InboundFrameList wird wohl irgendwie kein Weg vorbeiführen... :nixweiss:

Aber, ehrlich gesagt, mir ist sowieso schleierhaft, wie du den Methoden-Call (abstrahiert) "durchreichen" willst. :gruebel: Das geht doch immer nur für bekannte Methoden, oder klemmt mir da wieder ein Synapse? :lupe:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 07.03.12 01:04 
*Mit Zaun wedel* array of const AKA array of TVarRec :mrgreen:

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 07.03.12 01:16 
Hallo, danke für die Antwort.
Ja, Dispatcherkrams ist da. Geht nur noch darum wie die aussehen soll ;)
Kurzfassung: es gibt z.B. auf dem Client eine Funktion:
EntityCall(EntityID: Cardinal; Function: Word; Params: ????).
Die baut daraus eine TCmdSeq mit PacketID ENTITY_CALL und den Argumenten EntityID, Function, Param1, Param2, ..., ParamN
Auf dem Server wird im OnExecute das zerpflückt und ein OnEntityCall(Entity, Func, ???) aufgerufen.
Dort bindet der User seinen Dispatcher zu den Entities an und diese wiederum machen dann je nach Function-Code was.

Die Parameter kann man als array of const reinschieben und auf der anderen Seite wieder so parsen. Das geht, Problem ist, dass da nur eine kleine Auswahl von Datentypen möglich ist. Byte/Word/Cardinal/Integer ist da alles eins. Variant wäre weniger problematisch, aber es passt immer noch nicht alles (Extended fehlt und ByteArrays z.B. sind sehr seltsam).
Ich hab schon überlegt, Parameterobjekte zu nehmen, die sich selbst serialisieren. Ohne anonyme Klassen (Hallo, Java) bedeutet das aber, dass haufenweise Klassen zu deklarieren und zu implementieren sind. Ich will ja grade sowas vereinfachen, nicht eine "Menge Code" durch eine andere "Menge Code" erledigen.
Wenn Delphi assoziative Arrays mit TypInfo hätte... *träum* :roll:



user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Mit Zaunpfahl wedel* array of const AKA array of TVarRec :mrgreen:
Lesen. Hirn anschalten. Nochmal lesen. Dann vielleicht posten.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 11.03.12 03:33 
Moin!

Jaa, nach intensivem Überlegen ;) würde ich zu einer (weiteren, nur für die Weiterverarbeitung benötigten) TInboundFrameList als Parameter-Konvention raten, eben genau so, wie es auch reinkommt, datentypenfrei. Das hat zwar den doofen "Nachteil", dass du dann die Parameter jedes mal kopieren musst, das sollte aber nicht so schlimm sein, da die Strings auf dem Heap ja referenzgezählt sind und nicht dupliziert werden sollten. Damit "überlässt" du ja quasi der Zielmethode die Wahl, was das für Parameter und wie sie handzuhaben sind. :idea: :nixweiss: Sobald du das typensicher haben willst, wird das mit Delphi wohl nicht so lustig werden... :?

Also kurz: OnEntityCall(Entity, Func, Params: TInboundFrameList)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.