![]() |
Datenaustausch zwischen 2 Programmen?
Hiho,
ich hatte ursprünglich vor meine Programme auf Multithreading umzustellen, um Laufzeit zu sparen. Dies funktioniert aber nicht, da die Datenbankanbindung die ich nutzen muss (Drittanbieter) nicht für sowas geeignet ist. Jetzt habe ich die Überlegung mir (wie bisher) ein Singlthreading Programm zu schreiben und das in eine Art Client/Server-Architektur einzubinden. Also Schemadarstellung ähnlich zum Thread-Ablauf:
Delphi-Quellcode:
das Ganze auf Programm Ebene:
Programm
|- Sammelt Anforderungen |- Gibt diese an Threads weiter |- Thread #1 verarbeitet x Anforderungen |- Thread #2 verarbeitet y Anforderungen |- Sammelt die erzeugten Daten der Threads |- Gibt Ausgabedaten aus
Delphi-Quellcode:
Sprich:
Programm 1
|- Sammelt Anforderungen |- Gibt diese an Unterprogramme weiter |- Programm 2 (Instanz A) verarbeitet x Anforderungen |- Programm 2 (Instanz B) verarbeitet x Anforderungen |- Sammelt die von den Unterprogrammen erzeugten Daten |- Verarbeitet Ausgabedaten Mehr oder weniger das gleiche Prinzip aber halt von Thread auf Programm-Ebene verlagert. ... Jetzt habe ich aber 1 großes Problem: Wie schaffe ich es, dass mein Hauptprogramm mit den Unterprogrammen "Programm 2" kommunizieren kann? So dass ich dem sage "Mach das" und am Ende auch dessen Ausgabe wieder auslesen, sammeln und weiterverarbeiten kann? Da müsste ich doch quasi eine Client-Server-Anwedung schreiben, oder? Programm 1 ist der Server der 2 oder mehr Clients startet, diese mit der Verarbeitung beauftragt und anschließend Daten von denen geliefert bekommt. Aber wie mache ich das? ... Oder kann ich die Kommunikation auch über OLE / COM z.b. regeln? Danke im Voraus cu Patrick |
Re: Datenaustausch zwischen 2 Programmen?
Named Pipes, IPC, MailSlots, IP, ...
|
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
IPC ist doch der Oberbegriff (inter process communication) oder hast du da noch was spezielles? |
Re: Datenaustausch zwischen 2 Programmen?
Ich finde Messages immer recht hübsch um Aktionen anzustoßen, und Memory-Mapping zum Teilen von Daten, die man nicht mehr in lParam und wParam quetschen kann :)
|
Re: Datenaustausch zwischen 2 Programmen?
Gibts da irgendwo ein kleines Tutorial oder Beispiele?
Habe im Moment das hier gefunden: ![]() Aber da werde ich nich so ganz schlau draus, bzw. weiß nich so recht wie ich da jetzt meine Datenstrukturen austauschen kann. |
Re: Datenaustausch zwischen 2 Programmen?
Da ich das gerade interessant finde und es eigentlich auch zum Thema passt:
Wie viel kann oder sollte man denn mit den genannten Möglichkeiten übertragen? |
Re: Datenaustausch zwischen 2 Programmen?
Schau mal hier:
![]() Hier wird mit Windows-Messages sehr einfach zwischen 2 Prozessen kommuniziert |
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
Habs auch schon ausprobiert und mit Strings funzt es wie im Beispiel wunderbar. Ich denke ja ma nich, dass das nen großen Unterschied macht, ob ich da jetzt Strings oder eine meiner eigenen Datenstrukturen als Zeiger hinterlege, oder? 1 kurze Frage noch zum Verständnis: Welche Bedeutung hat "TCopyDataStruct.dwData"? Für mich macht das jetzt den Eindruck, dass das Windows-technisch gesehen egal ist und nur für meine Programme frei definierbar is, damit ich ne Unterscheidung habe, um was für eine Art von Daten es sich da im mitgelieferten Pointer handelt, oder? |
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
Mailslots sollte man auch nicht mehr verwenden, da sie nur aus Kompatibilitätsgründen (LanMan) existieren. Pipes und SharedMemory ist eine gute Wahl. Jedoch sollte man immer daran denken, dass die Sicherheitseinstellung (Besitzer, DACL) nur den notwendigen Systemen (die beiden Progs) einen Zugriff gibt. Andernfalls kann es zu erfolgreichen Übernahmeversuchen kommen. Leider ist das nicht so ohne weiteres machbar im Userkontext und man muss daher seine Lese- und Schreibroutinen vor Pufferüberläufen etc. schützen. Für eine Dienstkommunikation ist es aber unabdingbar. |
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
Und ja, dwData kannst du frei verwenden. |
Re: Datenaustausch zwischen 2 Programmen?
@Dezipaitor
Für die Zukunft werde ich mir dann eventuell ma die Sache mit Pipes und Co. angucken aber für den Anfang und zum rumprobieren reicht mir glaube ich erst Mal das mit den Messages. :) |
Re: Datenaustausch zwischen 2 Programmen?
Ich habe so etwas mal mit den Winsockets gelöst.
(TCP/IP) Diese Art der Datenkommunikation ist im Vergleich zu den anderen aufgezählten Verfahren die langsamste. Für mich hatte das den Vorteil, das die Kopplung sehr lose ist und nicht in allen Programmen ein synchroner Verbindungsaufbau erfolgen muss. Ein Programm (Server) lauscht auf einem Port. Ich sende also eine Anfrage Server da? Kommt ein timeout, so starte ich das Serverprogramm. Es ist mit dieser Methode möglich, dass mehrere Programme auf dem gleichen Port lauschen. In diesem Fall muss das Nachrichtenpaket eine Adresse haben. Im meinem konkreten Beispiel fängt eine Nachricht z.B. mit der Folge RG-Y ..Datenpaket an. Die Kennung RG läßt nur den Reportgenerator aktiv werden. Y bedeutet, das der Empfang des Datenpaketes quitiert werden soll. Die Kennung EOJ wird von allen verstanden und beendet die Applikation. Letzendlich habe ich mit dieser Lösung ein größeres Programm modularisiert, indem ich es in mehrere EXE-File zerlegt habe. Gruß Peter |
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
|
Re: Datenaustausch zwischen 2 Programmen?
Zitat:
... Das Ganze hat in Test übrigens wunderbar funktioniert, aber in Produktion gibts natürlich wieder prompt Probleme. Ich schreibe jetzt in meiner Client-Anwendung in lpData den Zeiger auf meine Datenstruktur die ich per SendMessage verschicken möchte. Denn verschicke ich die Nachricht und die Serveranwendung erhält diese auch. Aber wenn ich dann in der Serveranwendung auf lpData zugreifen möchte bekomme ich ne Zugriffsverletzung. Was mache ich falsch? Client-Anwendung
Delphi-Quellcode:
Serveranwendung
procedure TfrmClient.sendStatus(msg: String);
var msgStruct: TIpcStatusMessage; dataStruct: TCopyDataStruct; hServerWnd: HWND; begin try lblStatus.Caption := msg; self.Update(); // build message struct msgStruct := TIpcStatusMessage.Create(); msgStruct.msg := msg; msgStruct.clientId := self.clientId; // build copy-data-struct dataStruct.dwData := IPC_MSG_UPDATE_STATUS; dataStruct.cbData := SizeOf(msgStruct); dataStruct.lpData := @msgStruct; // get server-window hServerWnd := FindWindowEx(0, 0, nil, PChar(SERVER_TITLE)); if hServerWnd <> 0 then SendMessage(hServerWnd, WM_COPYDATA, Longint(self.Handle), Longint(@dataStruct) ); except on e: Exception do begin ; end; end; end;
Delphi-Quellcode:
procedure TfrmServer.WMCopyData(var Msg: TWMCopyData);
var logMsg: TIpcStatusMessage; begin if msg.CopyDataStruct.dwData = IPC_MSG_REQUEST_CLIENT then begin end else if msg.CopyDataStruct.dwData = IPC_MSG_RETURN_OUTPUT then begin end else if msg.CopyDataStruct.dwData = IPC_MSG_UPDATE_STATUS then begin logMsg := Msg.CopyDataStruct.lpData; if logMsg <> nil then updateStatus(logMsg.msg, logMsg.clientId); end; end; |
Re: Datenaustausch zwischen 2 Programmen?
Du verschickst einen Zeiger auf eine Objektinstanz, welche ja auch nur ein Zeiger ist.
|
Re: Datenaustausch zwischen 2 Programmen?
Oh, das ging aber schnell ^^
Danke schomma, denn 1 Fehler konnte ich dadurch schomma finden: Client-Anwendung
Delphi-Quellcode:
Das ist natürlich doppelt gemoppelt...
dataStruct.lpData := @msgStruct;
Hab das jetzt geändert auf:
Delphi-Quellcode:
Dann bin ich jetzt in dem Sinne weiter, dass die Adresse die in lpData gespeichert wird, der von msgStruct entspricht (beides $A66A30).
datatStruct.lpData := msgStruct;
... Wenn der Server jetzt aber die Nachricht empfängt, steht dort nicht mehr $A66A30, sondern komischerweise $12FED0 Warum ändert sich dieser Zeiger, während des verschickens? ... Weiß das ich mich hier etwas doof anstelle, aber solche Dinge sind mir komplett neu, deswegen weiß ich da nich so recht, wo ich anfangen soll selbst zu suchen. *G* |
Re: Datenaustausch zwischen 2 Programmen?
Hast Du mal versucht, die Klasse gegen einen Record auszutauschen?
|
Re: Datenaustausch zwischen 2 Programmen?
So, habs jetzt mal mit ner Record versucht und nun funzt es, Danke! :)
1 Frage habe ich aber noch dazu, wäre ja auch sonst zu einfach. :D Mein TIpcStatusMessage sieht so aus
Delphi-Quellcode:
Ist also nur ne Textnachricht und zusätzlich ne ID, von welcher Client-Anwendung das kommt.
TIpcStatusMessage = record
msg: array[0..200] of Char; clientId: Integer; end; Wenn ich das Ganze wie oben beschrieben mit Array[0..200] of Char mache funktioniert das auch. Versuche ich aber z.B. "msg: String" bekomme ich dort an der Serveranwendung ne Zugriffsverletzung. Bei "PChar" bekomme ich dann widerum nur nen Leerstring usw. Ich schätze mal das hat was mit den verschiedenen Mechanismen der Datentypen zu tun, und mit Array funzt es ja auch, aber zum Verständnis wäre ich trotzdem dankbar, wenn mir Jemand so grob erklären könnte, warum ich ein fixes Array senden kann, einen String z.B. aber nicht. Danke! Patrick |
Re: Datenaustausch zwischen 2 Programmen?
Das liegt einfach daran, dass ein String auch nur ein Zeiger auf das erste Zeichen ist, wohingegen bei einem Array fester Größe dieses auch selbst übertragen wird.
|
Re: Datenaustausch zwischen 2 Programmen?
Delphi-Quellcode:
sollte auch gehen.
TIpcStatusMessage = record
msg: String[200]; clientId: Integer; end; Grüße Klaus |
Re: Datenaustausch zwischen 2 Programmen?
Jepp, das sind ja kompatible Datentypen.
|
Re: Datenaustausch zwischen 2 Programmen?
So, hab jetzt den halben bis ganzen Tag gebastelt, mein Programm mit Funktionalität ausgestattet, reichlich dazu gelernt, das Ganze zum Laufen bekommen und habe natürlich kurz vor Schluss wieder 1 Problem:
Die Rückgabe der verarbeiteten Daten vom Client zum Server. Das Problem hatte ich Heute Morgen schomma: Client sendet die Daten weg (dort sind sie korrekt) und am Server kommen diese "kaputt" an. Dann wurde mir ja geraten, anstatt die Daten in einer Klasse in einem Record zu speichern und dieses dann weg zu schicken. Das funktioniert dann auch. Mein Problem ist jetzt: Die Daten die ich zurück send möchte, kommen aus einer "Standardfunktion" die ich von mehreren Programmen nutze und jetzt nich ma so eben von Klasse auf Record umprogrammieren kann, da das auch div. andere Programme betreffen würde. Also wie schaffe ich es, dass ich über SendMessage auch Klassen und nicht nur Records verschicken kann? Oder geht sowas gar nicht? Zur Info Client-Anwendung
Delphi-Quellcode:
Server-Awendung
// sends the given client-struct to the server
procedure TfrmClient.ipcReturnClient(struct: TClient); var dataStruct: TCopyDataStruct; hServerWnd: HWND; logMsg: String; begin try // build copy-struct dataStruct.dwData := IPC_MSG_RETURN_OUTPUT; dataStruct.cbData := SizeOf(struct); dataStruct.lpData := struct; // um die Struktur geht es // get server-window hServerWnd := FindWindowEx(0, 0, nil, PChar(SERVER_TITLE) ); if hServerWnd <> 0 then SendMessage(hServerWnd, WM_COPYDATA, Longint(self.Handle), Longint(@dataStruct) ); // hier ist die Struktur noch ok except on e: Exception do begin logMsg := 'Fehler bei Rücksendung des Mandanten: ' + e.Message; ipcSendStatus(logMsg); end; end; end;
Delphi-Quellcode:
// processes the given returned output
procedure TfrmServer.ipcProcessReturnedOutput(dataStruct: PCopyDataStruct); var clientStruct: TClient; begin clientStruct := dataStruct.lpData; // hier ist die Struktur dann kaputt if clientStruct <> nil then begin returnList.Add(clientStruct); end; end; Danke nochmals Patrick |
Re: Datenaustausch zwischen 2 Programmen?
Du müsstest die Klasse in einen Stream schreiben und dann den Stream versenden.
Das geht entweder indem die Klasse so eine Funktion (classtostream) selber implementiert. Ansonsten gibt es noch die Streamingklassen (imho TReader+TWriter) von Delphi, welche aber nur published properties beachten. |
Re: Datenaustausch zwischen 2 Programmen?
Morgen!
Ok, behalte ich mal im Hinterkopf. Hab das Programm jetzt eh erst ma auf normalem Wege fertig gemacht, denn die Liste musste so allmählich fertig werden und ob das Programm jetzt 4 oder 2 Minuten rennt is ja nun nich soooo der Faktor bei einmaligen Listen. :D Ging ja bisher erst mal hauptsächlich um das Testen von solchen Methodiken und da bot sich das kleine Programm halt grade an. ^^ ... Kann mir jemand, damit ich das Ganze in Zukunft richtig mache, nen gutes Tutorial o. Ä. für Named Pipes / Memory Mappings empfehlen? Hoffe, dass ich dann auch nich mehr so viel nerven muss wie letzte Woche. :D :D :D Danke im Voraus cu Patrick |
Re: Datenaustausch zwischen 2 Programmen?
Nochmal zu Klasse vs. Record. Du könntest deiner Klasse theoretisch auch einen Adapter mitgeben, der die Werte dann als Record zurückgibt. Dann müsstest du nur die sendende Routine ändern. Alle alten Methoden können ja dann ohne Probleme auf der Klasse arbeiten. Hätte auch noch den charmanten Vorteil, dass du selektiv zurückgeben kannst, falls du mal Elemente in der Klasse hast, die nicht übertragen werden sollen / können.
|
Re: Datenaustausch zwischen 2 Programmen?
Nimm doch ein Stream.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz