Einzelnen Beitrag anzeigen

Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#16

Re: Stream über TCP - Blockaufteilung ?

  Alt 5. Dez 2009, 15:11
Message Framing wäre das Suchwort für Google.
Der Absender sendet einzelne Messages (=Botschaften, Befehle, Commands) in einen TCP/IP Stream und der Empfänger hat die Aufgabe
die einzelnen Messages auch dann sauber zu trennen, wenn er immer nur einzelne Bruchstücke bekommt.
Im Extremfall tröpfeln die Bytes einzeln ein.

Dazu kenne ich drei Varianten
1.) feste Blockgrösse, Sender und Emfänger vereinbaren eine feste Blockgrösse
Messages, die kleiner sind werden mit Leerzeichen oder #0 aufgefüllt
2.) Jede Message wird mit CR/LF abgeschlossen
3.) Jede Message beginnt mit einem 4-Byte Int, in dem die Anzahl der folgenden Nutzdaten vermerkt ist

Variante 1.) ist sehr unflexibel, Variante 2.) hat Vorteile beim Debuggen aber problematisch für binäre Daten
und Variante 3.) eignet sich am Besten für grosse binäre Daten

Das Grundprinzip wie man die Messages beim Empfänger bildet ist aber immer das Gleiche.
Man braucht einen globalen Puffer für die Verbindung.
Ich bevorzuge AnsiStrings, weil man sich so nicht um die Reservierung und Freigabe von Speicher kümmern braucht.

Wenn ein neues Stück des TCP/IP Stream eintrifft, hängt man es an die bisherigen Daten an:
buffer := buffer + newdata; Dann beginnt die Suche, ob im Puffer eine vollständige Message steckt.
Für den Fall der Variante 2.) sähe das so aus:
Delphi-Quellcode:
p := Pos(#13#10, buffer)
if p <> 0 then
begin
  // Message gefunden
  Message := Copy(buffer, 1, p-1); // Message rauskopieren
  Delete(buffer, 1, p+1); // und im Puffer löschen
end;
Die Message könnte nun über ein Event verarbeitet werden.
Aber halt, wir sind noch nicht fertig!
Es könnten weitere Messages im Puffer stecken.
Mit einer Repeat....Until Schleife prüft man so lange, bis man feststellt, dass keine weiteren Messages im Puffer stecken.
Danach ist der Puffer leer oder es steckt noch eine unvollständige Message im Puffer.

Man sollte eine maximale Message - Grösse definieren, um sich vor Denial-of-Service Angriffen zu schützen.
Wird die max. Grösse überschritten, wird die Verbindung getrennt.

Da bei einer TCP/IP-Verbindung Daten üblicherweise in beide Richtungen verschickt werden,
müssen beiden Seiten dieses Verfahren zum Message Framing implementieren.

[edit]link hinzu[/eddit]
fork me on Github
  Mit Zitat antworten Zitat