AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Klassen für einfache IPC (InterProzessCommunication)
Thema durchsuchen
Ansicht
Themen-Optionen

Klassen für einfache IPC (InterProzessCommunication)

Ein Thema von idefix2 · begonnen am 9. Mai 2010 · letzter Beitrag vom 10. Mai 2010
Antwort Antwort
idefix2
Registriert seit: 17. Mär 2010
Nachdem ich für mein Projekt so etwas brauche und nichts wirklich Fertiges gefunden habe, das man unmittelbar einsetzen kann, habe ich zwei Klassen für das einfache Versenden von Strings via Memory mapped files programmiert - die Klassen könnten aber bei Bedarf leicht für beliebige andere Datentypen angepasst bzw. erweitert werden.
Nachdem ich für meine Zwecke keine Unicode-Strings brauche, wird von allen Zeichen des Strings nur das niederwertige Byte übertragen, sodass der Puffer nur halb so gross sein muss wie bei Unicode-Zeichen. Auch das liesse sich bei Bedarf leicht ändern.
Die Kommunikation geht nur in eine Richtung, will man in beide Richtungen kommunizieren, brauchen beide Programme sowohl den Server als auch den Client.


Beim Programmieren des TIPCClient bin ich über ein Problem gestolpert, das ich nicht lösen konnte, und haBE deshalb darum herumprogrammiert. Es ist mir nicht gelungen, den Befehl OpenFileMapping so zu verwenden, dass er richtig funktioniert. Ich habe dann statt dessen CreateFileMapping mit wenn nötig gleich anschliessendem CloseHandle verwendet, ist etwas umständlicher, aber funktioniert. Für Hinweise, was an der anderen Variante (im Quellcode auskommentiert) falsch ist, wäre ich dankbar.

Die Klassen heissen TIPCServer und TIPCClient, TIPCServer dient zum Versenden der Nachrichten, TIPCClient zum Empfangen.

TIPCServer publiziert folgende Methoden:

constructor Create (const name: string; BufSize: integer);
Erzeugt ein Memory Mapped File mit der angegebenen Größe und dem angegebenen Namen. Die Grösse des Datenpuffers ist um 8 Bytes kleiner als die Grösse des Memorymapped files.
Achtung: Der Datenpuffer muss so gross gewählt werden, dass kein Überlauf entstehen kann (dass also nicht mehr Daten abgeschickt werden, als im Puffer Platz haben, bevor der Client sie abgeholt hat).

procedure Msg (const s: string);
Stellt den String S zum versenden bereit. Wenn schon ein String zum versenden bereit steht, wird dieser neue String unmittelbar an den vorigen String angehängt. Auf Empfängerseite wird #13 als Stringtrennzeichen interpretiert, d.h. der String 'abc'#13'xyz' kommt so an, als wären zwei Strings 'abc' und 'xyz' versendet worden.

procedure MsgPost;
Schickt den versandbereiten String ab.


TIPCClient publiziert folgende Methoden:

constructor Create (const name: string);
Hier muß nur der Name übergeben werden, der muss genau mit dem Namen übereinstimmen, der von TIPCServer verwendet wird.

function MitServerVerbunden: boolean;
Liefert true, wenn das MMF vom Server bereits erstellt wurde, sonst false.

function DatenDa: boolean;
Liefert true, wenn das MMF vom Server bereits erstellt wurde und neue Daten im Puffer sind, sonst false.

function GetString: string;
Holt den nächsten String aus dem Puffer. Enthält ein String ein oder mehrere #13 Zeichen, liefert Getstring bei jedem Aufruf nur den Teilstring bis zum nächsten #13. Sind keine daten zum abholen bereit, liefert Getstring den Leerstring zurück, desgleichen wenn das erste Zeichen im Puffer #13 ist.
Deshalb sollte vor dem Aufruf von GetString mit Hilfe der Funktion DatenDa überprüft werden, ob es überhaupt etwas zum Abholen gibt.


Jetzt wünsch ich noch viel Spass bei der Verwendung der beiden Klassen.
Angehängte Dateien
Dateityp: rar ipc_741.rar (2,1 KB, 85x aufgerufen)
 
omata

 
Delphi 7 Enterprise
 
#2
  Alt 9. Mai 2010, 21:53
Dann eben nicht...
  Mit Zitat antworten Zitat
idefix2

 
RAD-Studio 2009 Pro
 
#3
  Alt 9. Mai 2010, 23:30
Hmm, ein nettes Programm, und sicher auch sehr brauchbar, wenn man die Kommunikation in einem 2. Thread ablaufen lassen will. Hat aber nicht mehr viel mit dem gemeinsam, was ich im Sinn hatte: nämlich zwei möglichst einfach und flexibel zu verwendende, gegebenenfalls auch leicht erweiterbare Units (z.B. hinsichtlich anderer Datentypen) für IPC zu schreiben. Durch die Callback Routine - die Frequenz sollte eigentlich vom Aufrufer einstellbar sein - ist man diesbezüglich wahrscheinlich eingeschränkter, jedenfalls sind Anpassungen nicht mehr so einfach zu machen. Durch die Organisation mit Thread und Callback-Funktion wird dem Benutzer der Unit eine starrere Anwendungsstruktur aufgezwungen (oder er muss die Daten in der Callback Routine extra puffern, und wieder eigene Prozeduren zum Abholen der Daten schreiben), als wenn die Daten einfach mit GetString, oder in weiterer Folge mit GetByte, GetReal oder überhaupt GetMyRecord abgeholt werden können, wann und WIE immer es günstig erscheint - vorausgesetzt, der Puffer ist ausreichend dimensioniert.

Ich würde meinen, es wäre besser, den Thread als separate Klasse zu programmieren, der ihrerseits die ursprüngliche IPCClient Klasse verwendet, um die Daten abzuholen. Damit stünde die Threadfunktionalität zusätzlich zu den Möglichkeiten der Originalklasse zur Verfügung, die ja auch völlig asynchron verwendet werden kann.

Den Sinn einiger Deiner Änderungen habe ich nicht verstanden, z.B. wozu Du eine protected und eine public isData Funktion samt Rekursion eingeführt hast, die gemeinsam nicht mehr tun als der ursprüngliche 5-Zeiler, und wozu Du den Type Buffer in einer eigenen Unit veröffentlichst - Ich habe ihn bewusst in den protected Bereich der beiden Klassen gelegt, weil die interne Struktur für den, der die Klassen verwendet, nicht relevant ist und ich sie deshalb eben nicht öffentlich haben wollte. Natürlich muss bei einer Änderung der Struktur in beiden Units diese Änderung parallel gemacht werden, aber nachdem bei einer solchen Änderung ohnedies auch der Programmcode in beiden Units entsprechend angepasst werden müsste, ist das ziemlich egal.

{$R-} ist die Delphi Defaulteinstellung, man sollte das vielleicht zur Sicherheit zusätzlich an den Anfang der beiden Units setzen. Nach den kritischen Stellen, wo eine Bereichsprüfung eine Exception auslösen würde, für den ganzen weiteren Code die Bereichsprüfung - entgegen den Delphi Defaulteinstellungen - einzuschalten, halte ich nicht für eine gute Idee - obwohl es zumindest beim aktuellen Code ziemlich egal ist, weil dort, glaube ich, keine Bereichsprüfungen mehr in Frage kommen. Aber andere Units übersetzt Du ja normalerweise auch nicht mit {$R+}, oder?
  Mit Zitat antworten Zitat
omata

 
Delphi 7 Enterprise
 
#4
  Alt 9. Mai 2010, 23:43
Und noch ein Kommentar: Man merkt, du hast gar keine Anhnung, was ich da eigentlich gemacht habe. Aber das ist ja auch egal.
  Mit Zitat antworten Zitat
wine

 
Delphi 7 Personal
 
#5
  Alt 10. Mai 2010, 01:54
Hatte mir den von Omata überarbeiteten SourceCode mit Beispiel aus #2 heruntergeladen, habe ihn mir aber noch nicht angesehen. Aber "mit Beispiel" klingt immer ganz gut

Der eine hat Dephi 7 Enterprise, der andere RAD-Studio 2009 Pro?

Zickenkrieg in OpenSource wegen falscher Schuhgrösse oder was?

Gegenseitige Beleidigungen werden NIEMANDEM weiterhelfen...

Ruhig Brauner, brrrrrr, ruhig

wine
  Mit Zitat antworten Zitat
idefix2

 
RAD-Studio 2009 Pro
 
#6
  Alt 10. Mai 2010, 07:02
Es tut mir leid, dass ich Dich offensichtlich schwerstens beleidigt habe, was überhaupt nicht meine Absicht war.

Der Ansatz, den Datenempfang im Hintergrund in einem Extrathread zu automatisieren, ist zweifellos für viele Situationen ein sehr guter. Ich würde meinen, dass die von Dir programmierte Threadklasse eine feine Ergänzung des TIPCClient wäre, ich würde sie aber nicht als Ersatz sehen, weil es auch Situationen gibt, in denen man eine Kommunikation im Hintergrund nicht braucht oder nicht will.

Optimal wäre meiner Meinung nach eine zusätzliche Klasse TIPCThread, die ihrerseits TIPCClient zum Abholen der Daten verwendet.

Es tut mir leid, dass das offenbar ganz anders hinübergekommen ist.

Die Frage nach der Motivation für die Änderungen, die ich nicht verstanden habe, war genau so gemeint, wie ich es geschrieben habe - ich verstehe es wirklich nicht und würde es gerne wissen.
  Mit Zitat antworten Zitat
Benutzerbild von spaxxn
spaxxn

 
Delphi XE2 Enterprise
 
#7
  Alt 10. Mai 2010, 07:42
Gibt ja zum Glück Interfaces und Vererbung
  Mit Zitat antworten Zitat
Antwort Antwort


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 18:56 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