AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Indy10 Write&ReadStream TArray<String>
Thema durchsuchen
Ansicht
Themen-Optionen

Indy10 Write&ReadStream TArray<String>

Ein Thema von hzzm · begonnen am 17. Mai 2017 · letzter Beitrag vom 18. Mai 2017
Antwort Antwort
hzzm

Registriert seit: 8. Apr 2016
103 Beiträge
 
Delphi 10 Seattle Professional
 
#1

Indy10 Write&ReadStream TArray<String>

  Alt 17. Mai 2017, 11:44
Ich versuche, String-arrays dynamischer Laenge deklariert mit TArray<String> mit indy10 in Delphi10Seattle vom Server zum Client schicken zu lassen.
Ich habe mich fuer die Variante mit automatischer StreamLength Uebermittlung entschieden:

Type
Code:
  TTestRecord = TArray<String>;
Server
Code:
procedure TStatusForm.IdTCPUpdateCommands;
var
  S: String;
  I: Integer;
  AStream: TMemoryStream;
  ALength: Integer;
  AContext: TIdContext;
  AClientList: TList;
  ATestRecord: TTestRecord;
begin
  SetLength(ATestRecord, 3);
  ATestREcord[1] := 'Tester';
  if not Assigned(IdTCPServer1.Contexts) then Exit;
  try
    AClientList := IdTCPServer1.Contexts.LockList;
    for I:=0 to AClientList.Count-1 do
    begin
      AContext := TIdContext(AClientList[I]);
      try
        if AContext.Connection.IOHandler.InputBufferIsEmpty then
          AContext.Connection.IOHandler.CheckForDataOnSource(0);
        while not AContext.Connection.IOHandler.InputBufferIsEmpty do
        begin
          S := AContext.Connection.IOHandler.ReadLn;
          if S = 'SendMeTheRecord' then
          begin
            try
              AStream := TMemoryStream.Create;
              ALength := Length(ATestRecord);
              AStream.Position := 0;
              AStream.Write(ALength, SizeOf(Integer));
              AStream.Write(ATestRecord[0], SizeOf(ATestRecord[0])*ALength);
              AContext.Connection.IOHandler.Write(AStream, 0, True); // mit schreiben der Laenge
            finally
              AStream.Free;
            end;
          end;
        end;
      except
        on E: Exception do
          AContext.Connection.Disconnect;
      end;
    end;
  finally
    IdTCPServer1.Contexts.UnlockList;
  end;
end;
Client
Code:
procedure TTransfer2Frame.Button1Click(Sender: TObject);
var
  AStream: TMemoryStream;
  ALength: Integer;
  ASize: Integer;
  ATestRecord: TTestRecord;
begin
  TCP2Frame.IdTCPClient1.IOHandler.WriteLn('SendMeTheRecord');
  try
    AStream := TMemoryStream.Create;
    TCP2Frame.IdTCPClient1.IOHandler.ReadStream(AStream, -1, False); // mit Laengenangabe
    AStream.Position := 0;
    AStream.Read(ALength, SizeOf(Integer));
    SetLength(ATestRecord, ALength);
    AStream.Read(ATestRecord[0], SizeOf(ATestRecord[0])*ALength);
  finally
    AStream.Free;
  end;
end;
Wenn ich mein TestRecord auf TArray<Integer> ummuenze, geht alles. Ein Testwert auf array[1] kommt an.
Mit den Strings verbockt er es aber. Es kommt entweder chinesischer Zeichen-Salat statt "Tester" oder "Nicht verfuegbarer Wert". Warum passiert das und wie kann ich die Situation elegant loesen?

Geändert von hzzm (17. Mai 2017 um 11:49 Uhr) Grund: inhaltlich korrigiert
  Mit Zitat antworten Zitat
hzzm

Registriert seit: 8. Apr 2016
103 Beiträge
 
Delphi 10 Seattle Professional
 
#2

AW: Indy10 Write&ReadStream TArray<String>

  Alt 17. Mai 2017, 13:19
Hat sich erledigt.
Eigentlich voellig klar:

String ist selbst ein dynamisches array of Char.
Solange man keine fixen Laengen verwendet (TArray<String[30]>), muesste man fuer jeden String individuell die Laenge uebermitteln, wie in meinem Beispiel eine Ebene hoeher fuer Length(TArray<String>) bereits geschehen.

Die ganze Serialisier-Story in delphi habe ich noch nich wirklich befriedigend geloest. Egal ueber welche Streams ich meine Daten jagen will, immer laeuft es darauf hinaus, alles undynamisch zu behandeln. Schade.

Ich kann nicht recht glauben, dass jeder andere Indy-user nur fixed-length Strings uebertraegt.
Oder deren Struktur so simpel ist, dass sie immer nur einen einzelnen String versenden, dessen Laenge sich dann aus dem IOhandler ergibt.

In der Praxis ist es doch zumeist so: Du hast eine ObjectList, die ein dynamisches Array of Record enthaelt, der wiederum...
und dann willst Du den ganzen Kaese ueber TCP/IP uebermitteln.

Ich kann doch nicht der einzige mit dem Problem sein, keinen Bock darauf zu haben, in jeder logischen hierarchie-Ebene zig Laengen von dynamischen Typen einzeln abzugurken.
Wie macht ihr das denn?

Geändert von hzzm (17. Mai 2017 um 13:35 Uhr)
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#3

AW: Indy10 Write&ReadStream TArray<String>

  Alt 17. Mai 2017, 14:34
Der Server geht durch alle Connections und schaut ob Nachrichten vom Client empfangen wurden

Macht man das nicht normalerweise in der OnExecute Methode? Diese wird ja im speziellen Threadkontext der Connection ausgeführt, so dass man sich das LockList Gedöns sparen kann und ohne Schleife auskommt.
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
hzzm

Registriert seit: 8. Apr 2016
103 Beiträge
 
Delphi 10 Seattle Professional
 
#4

AW: Indy10 Write&ReadStream TArray<String>

  Alt 17. Mai 2017, 14:57
Der Server geht durch alle Connections und schaut ob Nachrichten vom Client empfangen wurden

Macht man das nicht normalerweise in der OnExecute Methode? Diese wird ja im speziellen Threadkontext der Connection ausgeführt, so dass man sich das LockList Gedöns sparen kann und ohne Schleife auskommt.
Code:
procedure TStatusForm.IdTCPServer1Execute(AContext: TIdContext);
begin
  IdTCPUpdateCommands;
end;
Ja, stimmt. Wenn ich die Funktion nicht woanders noch ohne AContext aufrufen wuerde, koennte ich mir die Schleife sparen.
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#5

AW: Indy10 Write&ReadStream TArray<String>

  Alt 17. Mai 2017, 15:48
Egal ueber welche Streams ich meine Daten jagen will, immer laeuft es darauf hinaus, alles undynamisch zu behandeln. ... Ich kann nicht recht glauben, dass jeder andere Indy-user nur fixed-length Strings uebertraegt.
Oder deren Struktur so simpel ist, dass sie immer nur einen einzelnen String versenden, dessen Laenge sich dann aus dem IOhandler ergibt.
Läuft es nicht eher auf eine bewährte™ Lösung mittels JSON oder XML hinaus?

Dabei wird alles in einen strukturierten String geschrieben, dieser hat eine bestimmte Länge.

In der Praxis (Protokolle wie AMQP oder MQTT) baut man dann noch einen Block mit Zusatzdaten davor, der aber protokollspezifisch ist und mit bekannten Längen und Trennzeichen arbeitet. Die Payload (Body) ist dann ein Binärblock oder eben ein z.B. nullterminierter String.
Michael Justin

Geändert von mjustin (17. Mai 2017 um 15:51 Uhr)
  Mit Zitat antworten Zitat
hzzm

Registriert seit: 8. Apr 2016
103 Beiträge
 
Delphi 10 Seattle Professional
 
#6

AW: Indy10 Write&ReadStream TArray<String>

  Alt 18. Mai 2017, 07:35
Läuft es nicht eher auf eine bewährte™ Lösung mittels JSON oder XML hinaus?
Wie serialisiere ich denn in Delphi auf die Schnelle?
Ich bin schon eine ganze Weile lang auf der Suche nach einem brauchbaren XML-serializer, finde aber meist schon tote Projekte.

Wenn ich Dich richtig verstehe, sagst du, es gaebe ein Mittel, mit dem ich dynamische Typen (arrays of records of strings o.ae.) einfach nach XML serialisieren kann.

Wie?
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Indy10 Write&ReadStream TArray<String>

  Alt 18. Mai 2017, 09:53
Läuft es nicht eher auf eine bewährte™ Lösung mittels JSON oder XML hinaus?
Wie serialisiere ich denn in Delphi auf die Schnelle?
Mit JSON!
https://community.embarcadero.com/bl...ne-of-code-497
  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 19:35 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