Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy 10 TCP Client Server -> MemoryStreams übertragen (https://www.delphipraxis.net/170904-indy-10-tcp-client-server-memorystreams-uebertragen.html)

stahli 9. Okt 2012 15:33

Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
-> Delphi XE Prof, Indy 10

Hintergrund: Ich möchte StringListen zwischen Client und Server übertragen.
Die Strings können SEHR lange Zeilen enthalten, da ich u.U. Bilddaten als Base64 übertragen will.

Teilweise kann ich bereits Daten übertragen. Ich möchte jedoch unterschiedliche Varianten austesten und habe dazu mal ein Testprojekt erstellt.
Das Projekt (XE) ist angehängt.

Die Problembeschreibung ist schwierig, da die Probleme bei unterschiedlichen Varianten in verschiedenen Formen auftreten.
Daher habe ich dies mal als Video erstellt: http://youtu.be/d852TASq34c

Im wesentlichen gib es folgende Fragen:
- Wie kann ich die übertragenen Daten in Memos schreiben, ohne dass es Syncronisationsprobleme gibt? (Bei manchen Versuchen hat es funktioniert, aber nicht immer.)
- Wie funktioniert die Übertragung (ReadLn und WriteLn) mit einem Endekennzeichen (#0 oder '|') in beide Richtungen?
- Wie funktioniert die Übertragung über Streams in beide Richtungen?

Ich habe viel im Netz gesucht, bin aber bisher nicht zurecht gekommen.
Vielleicht können wir das Projekt mal so ausbauen, dass wir hier ein komplettes Demo für die unterschiedlichen Übertragungsformen haben...

Zur Umschaltung der Übertragungsform habe ich eine Compilerkonstante eingerichtet:
Delphi-Quellcode:
const
  CompileModeFoot = 0;
  CompileModeLinesChanged = 1;
  CompileModeLinesEnd = 2;
  CompileModeStream = 3;
  CompileMode = CompileModeStream; // <- hier auswählen
Da die auftretenden Probleme recht komplexe Zusammenhänge haben, ist natürlich auch das Demoprojekt und die Fehlerbeschreibung etwas umfangreicher.
Wäre nett, wenn sich mal jemand die Zeit nehmen könnte...

daywalker9 9. Okt 2012 15:37

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Gelöscht

Bummi 9. Okt 2012 15:49

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
vielleicht ist auf der Seite http://www.atozedsoftware.com/Indy/D.../index.EN.aspx
der Link Live Stream http://downloads.atozed.com/indy/10/LiveStream.zip interessant für Dich.

stahli 9. Okt 2012 19:57

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Hallo Bummi,

ich bin nicht sicher, ob ein HTTP-Server identisch zu nutzen ist...

Danke dennoch. Ich schaue es mir an, komme aber erst die nächsten Tage dazu.

stahli 21. Okt 2012 23:42

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Der Link hat mich nicht konkret weiter gebracht.

Ich habe mein Demoprojekt einmal etwas vereinfacht und zunächst einmal versucht, die Rückgaben an die GUI (Memos und Button.Caption) threadsicher zu machen.
(Orientiert habe mich hieran: http://www.devarticles.com/c/a/Delph...n-in-Delphi/1/)

Allerdings komme ich damit auch nicht zurecht, da ich nicht verstehe, wie viele und welche Threads ich brauche, um das zu gewährleisten...
Es müssten 4 Memo-Ausgaben und das Schreiben in Button.Caption syncronisiert werden.

Wenn ich das so mache wie im verlinkten Beispiel funktioniert schon die Behandlung der Client-Read-Funktion nicht mehr.

Ich hätte auch eher versucht, in den Methoden:
Delphi-Quellcode:
procedure TFormIndy10TCPStreamTest.ButtonRandomClick(Sender: TObject);
procedure TFormIndy10TCPStreamTest.IdTCPServerTestExecute(AContext: TIdContext);
einen Thread mit einer anonnymen Methode zu starten und dort die eigentliche Behandlung vorzunehmen.

Kann mir jemand auf die Sprünge helfen?

Danach würde ich dann die verschiedenen Übertragungsformen testen (die lässt sich jetzt einfach über eine RadioGroup auswählen).

Bummi 22. Okt 2012 07:35

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe nur ein paar Stellen angebastelt, vielleicht hilft es trotzdem weiter ...

stahli 22. Okt 2012 22:10

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
@Bummi: :love:

Ich habe das Projekt mal weiter ausgebaut und aufgeräumt...

Folgender aktueller Stand:

+ die Übertragung "zu Fuß" und "changed" funktioniert wunderbar
- wenn allerdings "Show Info" eingestellt ist, dann dauert die Anzeige in den Memos ungefähr 20 Sekunden

- die Übertragung mit Endekennzeichen #0 funktioniert nur ein mal
- Endezeichen '|' funktioniert gar nicht

- die Übertragung per Stream liefert einen Leerstring

Werde mal sehen, ob ich morgen weiter komme...

Vielleicht wäre es grundsätzlich sinnvoll, die "Infos" in einem Protokoll-Array oder -List zu sammeln und bei Gelegenheit aus der Anwendung heraus (Timer/OnIdle) in die Memos zu schreiben.
Das Array müsste aber dann ja auch thread safe sein...

Bummi 22. Okt 2012 22:32

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Hi André,

wenn ich mir so anschaue womit Du Dich im allgemeinen beschäftigst (auch das Thema Livebindings via TCPIP) bin ich nicht sicher ob der INDY-Weg der optimale ist. Gegf. wäre es einfacher/übersichtlicher mit weniger "fetten" Komponenten wie z.B. TTcpServer mit im GetThread von TClientSocketThread abgeleiteten eigenen Threads, das Senden über Threads mit TTcpClient....
Zumindest ist dann der jeweilige Kontext für Dich(mich) transparent, Deadlocks, Blockings etc. leichter zu vermeiden.

bernhard_LA 23. Okt 2012 13:28

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
kennt Ihr demo Demo projekts auf Source forge zu diesem Thema "delphi + INDDY 10" und Tanta Google kennt den Link :-)

stahli 23. Okt 2012 14:03

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Selbstverständlich - jedenfalls grundsätzlich. :wink:

Ich hatte auch Deinen Beitrag hier gefunden.

Allerdings tue ich mich mit dem neumodischen svn-Kram altersbedingt etwas schwer :oops: und da das Beispiel offenbar nicht threadsafe ausgelegt ist, habe ich es dann (erst mal) nicht weiter verfolgt...

Gestern habe ich dann mal einen ersten Versuch mit TCPClient/TCPServer unternommen und das sieht mir wirklich übersichtlicher aus (habe aber erst mal nur einen Stream vom Client zum Server geschickt).

bernhard_LA 23. Okt 2012 15:25

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
für svn > tortoise installieren und dann der Anleitung im Projekt befolgen.... bin mittlerweile ein großer Fan von svn + Tortoise

Thread Safe : welche Punkte im Code sind Dir aufgefallen ?
VCL Ausgaben im Indyserver.execute muss ich noch entfernen
mein ziel ist schon Thread Safe samples zu erstellen

stahli 23. Okt 2012 23:24

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich bin doch wieder bei Indy. Das erscheint mir komfortabler und das Problem mit der GUI-Syncronisation besteht bei der flachen Variante ja auch.

Die Übertragung mit dem Ende-Kennzeichen ist gelöst.
Die Lösung habe ich hier gefunden: http://stackoverflow.com/questions/1...nd-line-breaks
-> IdTCPClient.IOHandler.Write Ln (S + #0);
Man darf beim Schreiben nicht WriteLn verwenden, da sonst ein #13#10 angehängt wird. Beim Lesen wird dann bis zum Endekennzeichen gelesen und der Zeilenumbruch verbleibt im Puffer. Dadurch hakt im weiteren Verlauf die Kommunikation.
In gewisser Weise macht das Sinn. ;)

Die Übertragung per Stream funktioniert grundsätzlich auch - ABER!
Die Größe des eingehenden Streams kann ich noch nicht ermitteln. Im Test kürze ich den Steam jetzt auf 14 Byte und lese 14 Byte aus. So ist erkennbar, dass die Übertragung perfekt funktioniert.
Jetzt müsste ich noch eine Möglichkeit finden, InputStream.Size vor dem Lesen des Streams zu ermitteln. Dann wären alle Übertragungsvarianten fertig.


Die syncronisierte Ausgabe in die Memos werde ich dann in einem Tread versuchen, der dazu auf die Syncronisation mit dem MainThread wartet.

Bummi 24. Okt 2012 07:18

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Du schickst einfach vorneweg die Länge des Streams z.B. in einem DWord/Cardinal und liest das als erstes aus.

bernhard_LA 24. Okt 2012 07:29

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Das problem mit de Länge des Streams sollte eigentlich in meinem samples gelöst sein

(einfach mal das Video Play Badminton) als *.swf Datei ansehen


Zum Thema VCL syncro folgender Link http://stackoverflow.com/questions/9...ng-application

In meiner eigene app habe ich ein TTHread.syncronize(nil, meineGUIupdate); eingebaut
Dieses Thema ist heute noch nicht in den samples eingebaut

bernhard_LA 24. Okt 2012 17:26

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
in den source forge INDY 10 TCP Client Server Demos ist die ganz GUI interaction immer mit IDNotify( GUIprocedure) ; abgeschottet. vermutlich reicht es aus nur


Delphi-Quellcode:
TCPserver.Onexecute(----);
     

     .....
    GUIProcedure;
    TTHreadSyncronize(nil, GUIProcedure);
    ....

end;
als Strickmuster zu befolgen.

stahli 24. Okt 2012 21:56

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Bernhard,

vielen Dank schon mal für Deine Demos!
Ich habe mir mal 4 Funktionen ausgeliehen ;-)

Die 4 Varianten der Datenübertragung funktionieren jetzt einwandfrei. :)

Die GUI-Syncronisation habe ich jedoch noch nicht hin bekommen.
Eine IdAntiFreeze verhindert zwar ein Einfrieren, verzögert aber den gesamten Ablauf EXTREMST.

Deinen Hinweis kann ich leider nicht genau einordnen. Kannst Du das konkretisieren?

Ich hätte von mir aus einen Thread gestartet, dem ich im Execute einen "Modus" und einen "String" übergebe.
Im Syncronisize würde ich den String dann je nach Modus an eine der 4 Log-Funktionen geben.
Ist das zu kompliziert?

bernhard_LA 24. Okt 2012 22:28

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
ich habe mich bei meiner Lösung an diesem Thema orientiert http://stackoverflow.com/questions/1...-safe-vcl-code;

Der Trick war bei mir TTHtread.syncronize ( Nil -> hält den server execute Thread an, Meine GUI Funktion -> bitte zuerst hier alle Ausgaben); ich habe meine Demos noch nicht mit dieser Technik getested, ich verwende dieser Schema bei meiner Produktiven Anwendung.

Kennst du diesen link http://stackoverflow.com/questions/9...ng-application

stahli 25. Okt 2012 21:07

AW: Indy 10 TCP Client Server -> MemoryStreams übertragen
 
Liste der Anhänge anzeigen (Anzahl: 2)
SEHR SCHÖN!

Also jetzt funktioniert (fast) alles wunderbar und ist m.E. ein sehr schönes Demoprojekt, um Indy-Streams nachzuvollziehen.

Zwei kleine Schönheitsmankos:
-> InfoClientIn wird an 4. Stelle aufgerufen, aber schon an zweiter dargestellt. (Das ist aber ja in einer realen Client/Server-Anwendung kein Problem.)
-> Die MemoServerOut.Scrollbar wird nicht an´s Ende gesetzt.

Die VCL-Syncronisation für Client-Infos ist nicht erforderlich, kann aber dennoch durchgeführt werden.
Syncronisation ist immer beim Server notwendig wenn man VCL-Ausgaben durchführt.

Jetzt kann ich mal schauen, ob ich das so auf mein eigentliches Projekt umsetzen kann... :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:59 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