Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Dynamischen Record mir sendbuff (TServerSocket) versenden (https://www.delphipraxis.net/110769-dynamischen-record-mir-sendbuff-tserversocket-versenden.html)

Jackie1983 24. Mär 2008 15:20


Dynamischen Record mir sendbuff (TServerSocket) versenden
 
hi zusammen,

erst mal Frohe Ostern :)
Möchte gerne folgeneden Record versenden
Delphi-Quellcode:
 
  TDatenPack = packed record
    dCMD : string[10];
    dParam : string; // <- edit
  end;
dParam hat keine feste länge. Diese speicher ich im Header.

Das versenden mache ich wie folgt
Delphi-Quellcode:
var
  daten : TDatenPack;
  s,sDaten : string;
begin
  s := 'Text';
  daten.dCMD := 'COMMAND';
  setlength(daten.dParam,Length(s));
  daten.dParam := s;
  header.hDynSize := Length(s);

  setlength(sDaten,SizeOf(Daten));
  Move(Daten,PChar(sDaten)^,SizeOf(Daten));
  fClient.Socket.SendBuf(PChar(sDaten)^,length(sDaten));
end;
Irgend wo muss da noch ein Fehler sein....

marabu 24. Mär 2008 17:41

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
Hi Jackie,

dir auch Frohe Ostern.

Dynamisch wäre dein Record dann, wenn du den benötigten Speicherplatz explizit zur Laufzeit anfordern würdest - tust du aber nicht.

Weiter enthält dein Record zwei ShortStrings, die du fix auf 11 und 2 Byte dimensioniert hast - jeweils das erste Byte enthält die tatsächlich benutzte Anzahl von Zeichen, die du mittels Length() abfragen und mittels SetLength() festlegen kannst.

Groben Unfug treibst du, wenn die Länge deines dParam mittels SetLength() auf vier setzt, durch die vorherige statische Dimensionierung aber nur maximal ein Byte nutzbarer Speicher festgelegt wurde. Beim Zugriff auf dParam wird dann ein Speicherbereich gelesen bzw. geschrieben, der eigentlich Variablen beherbergt, die vom Übersetzer direkt "hinter" deinen Record gelegt wurden.

Ahnst du schon etwas?

Durch die übliche Speicherausrichtung kannst du gerade noch drei zusätzliche Bytes in deinen Record packen, bevor der Zeiger auf s, der gleich anschließend gespeichert ist, von deiner Zuweisung an dParam überschrieben wird.

Freundliche Grüße

Jackie1983 24. Mär 2008 17:56

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
habe ein fehler gemacht.
Es sollte nicht string[1] sein sondern nur string;

marabu 24. Mär 2008 18:20

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
Jetzt hast du aus dem ShortString einen AnsiString gemacht. Der Speicherplatz für dParam liegt dann aber außerhalb deines Records und dParam selbst ist intern zu einem Pointer auf diesen Speicher geworden. Damit wird dein Record als Versandeinheit unbrauchbar. Pointer eignen sich nicht für den Versand, da sie nur im aktuellen Adressraum eine Bedeutung haben.

Betrachte mal SizeOf(daten) nachdem du SetLength(daten.dParam, 100) ausgeführt hast.

Jackie1983 24. Mär 2008 18:26

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
sizeof gibt 2??? ist das jetzt nur der pointer?
ich check nichts mehr. Wie kann ich den String den eine feste länge geben?
PChar?

marabu 24. Mär 2008 18:35

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
Offensichtlich hast du etwas anderes als meinen Vorschlag geprüft.

Eine feste Länge gibst du einem String durch die Angabe der maximalen Länge bei der Typvereinbarung: string[1] bis string[255] sind möglich.

Jackie1983 24. Mär 2008 18:47

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
sorry habe mich beschissen ausgedrückt.....
Wenn ich einen var als Sring[255] deklariere ist es kein Thema mit der Übertragung. Kann aber nur 255 zeichen übertragen. Deswegen möchte ich einen dyn. String übertragen, nur das klappt nicht so ganz. Muss die Größe ja irgend wie mit übertragen .....
Delphi-Quellcode:
Type
  THeader = record
    daten
    Strlength : integer; //<- die länge des dyn strings
  end;
  TDaten = record
    cmd : string[20];
    dyn : string;
  end;
//edit
irgend wie muss ich die den Record in einen String bekommen
Move(pDaten,PChar(sDaten)^,Sizeof(TDaten) + header.Strlength ); //pDaten = TDaten

marabu 24. Mär 2008 19:07

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
Wenn du mehr als 255-stellige Strings versenden möchtest, dann würde ich nicht mit Records arbeiten. Du kannst sie einzeln oder auch mehrere auf einmal versenden:

Delphi-Quellcode:
function BufferAddString(var buffer: string; const s: string): Cardinal;
var
  index, bytes: Cardinal;
begin
  index := Succ(Length(buffer));
  bytes := Length(s);
  SetLength(buffer, 3 + index + bytes);
  Move(bytes, buffer[index], 4);
  Move(s[1], buffer[index + 4], bytes);
  Result := Length(buffer);
end;

// 

var
  buf: string;
  n: Cardinal;
begin
  buf := '';
  n := AddString(buf, 'COMMAND');
  n := AddString(buf, 'TEST');
  BufferSend(fClient.Socket.SendBuf(buf[1], n);
end;
Ich würde mir noch eine Funktion BufferSend() schreiben, der ich den Socket und den Buffer übergeben kann.

Jackie1983 24. Mär 2008 19:12

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
so hatte ich es mir auch schon gedacht. Ich persönlich finde es nur schöner wenn man direkt auf eine var zugreifen kann. also
begin
if meinrecord.cmd = 'LALA' then
aber wenn das so nicht möglich ist werde ich es so machen wie du oben beschrieben hast.
thx

marabu 25. Mär 2008 10:17

Re: Dynamischen Record mir sendbuff (TServerSocket) versende
 
Die diskutierten Probleme machen Records als Versandeinheit untauglich, zum Speichern der einzelnen Informationen in deinem Programm kannst du selbstverständlich Records benutzen.


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