Thema: Delphi max Länge TCPIP

Einzelnen Beitrag anzeigen

Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.836 Beiträge
 
Delphi 12 Athens
 
#14

AW: max Länge TCPIP

  Alt 6. Mär 2025, 19:25
Wenn ja, wie würde der Empfang aussehen, wenn man auf ein bestimmtes Line-Ending wartet?
Dazu haben QuickAndDirty und Mavarik oben schon etwas gesagt.

Stell dir ein Buch vor:
Du gehst Zeile für Zeile durch und erkennst an der Positionierung und Formatierung, wann du eine Seitenzahl und wann ein neues Kapitel vor dir hast. Aber du liest das Buch dabei einfach von vorne bis hinten, ohne dass du auf bestimmte Kennzeichen wartest.

Und genauso geht man auch bei einer solchen Übertragung vor. Stell dir ein ganz einfaches Protokoll vor: # ist der Start einer Überschrift, $ der Start einer Seitenzahl, am, - startet einen Text und Ende kommt immer ein *.

Beispiel:
$1*#Überschrift*-Das ist ein Text.$2*-Und noch mehr Text!**$44*#Überschrift*-Das ist ein kleiner Text.$45*-Und noch ein wenig Text!**

Nun bekommst du:
$1*#Überschrift*-Das ist e
Dann gehst du zeichenweise durch und fügst die Zeichen einzeln zu deinem Empfangspuffer (sprich eine Stringvariable) hinzu. Findest du ein doppeltes **, also dein Paketende, gibst du deinen Empfangspuffer als vollständiges Paket weiter und leerst ihn. Das machst du einfach immer so weiter, wenn du etwas empfängst. In diesem Fall wäre das Paket nicht vollständig, also wartest du weiter, bis du den nächsten Teil empfängst.

Pseudocode in etwa:
Code:
Buffer := '';
while Connection.Active do
begin
  if Connection.HasData then
  begin
    Data := Connection.GetData;
    FoundEndChar := False;
    for i := 1 do Length(Data) do
    begin
      Buffer := Buffer + Data[i];
      if Data[i] = EndeZeichen then
        if FoundEndChar then // das letzte Zeichen war schon ein EndeZeichen --> doppeltes Ende gefunden
        begin
          VerarbeitePaket(Buffer);
          Buffer := '';
          FoundEndChar := False;
        end
        else
          FoundEndChar := True // ein erstes EndeZeichen
      else
        FoundEndChar := False; // egal ob vorher ein einzelnes war oder nicht, aktuell kein EndeZeichen
    end;  
  end
  else
    Sleep(1); // kurz warten, damit die Schleife nicht so viel Leistung zieht
end;
Und zur Analyse: Du gehst durch...
$ --> Seitenzahl, also fängt ein Paket an.
1 --> Aktueller Status ist Seitenzahl
* --> Aktueller Status ist Seitenzahl, die ist damit vollständig --> Seite "2"
# --> Überschrift beginnt
Ü...t --> Überschriftsinhalt
* --> Überschrift beendet --> "Überschrift"
- --> Text beginnt
D..e --> weiterer Text

An der Stelle weißt du, dass das Paket noch nicht vollständig ist. Also wartest du auf den nächsten Teil, packst den hinten dran und prüfst erneut.

Und so gehst du einfach zeichenweise durch, merkst dir, wo du bist, prüfst, ob der nächste Inhalt so im Zusammenhang passt, ...
Am Ende bist du dann am ersten Sternchen, bist im Modus "im Paket" und bekommst das zweite Sternchen. Damit ist das Paket vollständig und du kannst es zur Bearbeitung weitergeben.

Das ist eine Möglichkeit. Das Prinzip nennt sich endlicher Automat. Du kannst die schon vorhandenen Teile des Pakets dabei direkt in einer Struktur ablegen und aus deinem Empfangsstring entfernen oder du machst das erst, wenn du das Ende hast.

Du kannst aber auch wie oben schon angesprochen wurde, die Länge direkt am Anfang mitschicken. Dann weißt du, wie viele Bytes danach kommen. Du kannst z.B. eine Überschrift so aussehen lassen:
PAKET54*#11*Überschrift*
PAKET --> neues Paket
5..4 --> Paketlänge
* --> Paket ist 54 Bytes lang
# --> Überschrift Start
1..1 --> Länge
* --> Überschrift ist 11 Bytes lang
...

Es gibt wirklich viele Möglichkeiten und das ist nur ein ganz kurzer Einstieg, damit du eine grundsätzliche Idee hast, wie du mit Datenströmen arbeiten kannst. Es gibt natürlich andere und sicher auch schönere Lösungen.

Die ganz simple Variante wäre, mit Pos in dem String nach dem Endezeichen zu suchen.
Sebastian Jänicke
AppCentral

Geändert von jaenicke ( 6. Mär 2025 um 19:28 Uhr)
  Mit Zitat antworten Zitat