TsgcWebTransportStream › Methoden › WriteData

WriteData Methode

Schreibt Anwendungsbytes in den Stream. Zwei Überladungen: rohe Bytes oder eine als UTF-8 kodierte Zeichenfolge.

Syntax

WriteData(const aData: TBytes) TBytes-Überladung

procedure WriteData(const aData: TBytes); overload;

Parameter

NameTypBeschreibung
aDataconst TBytesAnwendungs-Payload, unverändert geschrieben. Es wird nichts hinzugefügt und nichts interpretiert, dies ist also die Überladung für Binärprotokolle und für Daten, die Sie bereits codiert haben.

WriteData(const aData: string) String-Überladung

procedure WriteData(const aData: string); overload;

Parameter

NameTypBeschreibung
aDataconst stringText, der nach UTF-8 kodiert und anschließend geschrieben wird. Es gibt keine Byte Order Mark, keinen Terminator und kein Längenpräfix: genau die UTF-8-Bytes der Zeichenfolge.

Hinweise

Beide Überladungen übergeben die Bytes an den Writer des Streams, OnWriteBytes, den der Transport an den zugrunde liegenden QUIC-Stream gebunden hat. Der WebTransport-Stream-Header wurde bereits von OpenStream geschrieben, was Sie hier übergeben, ist also reine Anwendungs-Payload. Die String-Überladung ist eine Vereinfachung gegenüber der Byte-Variante: Sie kodiert nach UTF-8 und ruft denselben Pfad auf.

Dies ist ein Byte-Stream, keine Nachrichten-Warteschlange. Das ist das Wichtigste, was Sie über WriteData wissen müssen. QUIC liefert Ihnen einen geordneten Bytestrom ohne Satzgrenzen, es gibt also keine Garantie, dass ein WriteData am anderen Ende zu einem OnData wird. Zwei Schreibvorgänge können zu einem Lesevorgang zusammenfallen, und ein Schreibvorgang kann auf mehrere aufgeteilt werden. Wenn Ihr Protokoll Nachrichten kennt, rahmen Sie diese ein: Längenpräfix, Trennzeichen oder Datensätze fester Größe. Kurze Testzeichenfolgen kommen meist vollständig an, genau deshalb zeigt sich das Problem erst später unter Last und nicht während der Entwicklung.

Es meldet nichts. Kein Rückgabewert, keine Ausnahme bei einem Fehlschlag und keine Zustellbestätigung. Ein Schreibvorgang auf einen Stream, dessen QUIC-Stream nicht geöffnet werden konnte, oder auf das empfangende Ende eines unidirektionalen Streams verläuft stillschweigend im Nichts. QUIC garantiert innerhalb eines Streams eine zuverlässige, geordnete Zustellung, sobald die Bytes angenommen wurden, aber wenn Sie wissen müssen, dass der Peer etwas verarbeitet hat, muss Ihr Protokoll das ausdrücken.

Prüfen Sie vor dem Schreiben die Richtung. Sie dürfen auf jeden von Ihnen geöffneten Stream schreiben sowie auf einen vom Peer geöffneten bidirektionalen Stream, bei dem der Transport einen Writer zurück an den QUIC-Stream des Peers bindet. Ein vom Peer geöffneter unidirektionaler Stream ist auf Ihrer Seite nur zum Empfangen: Ein Schreibvorgang darauf bewirkt nichts Sinnvolles und meldet keinen Fehler. Sichern Sie Ihren Echo-Pfad mit if not aStream.Unidirectional ab.

Das Schreiben nach Close wird nicht blockiert. Close setzt nur ein Flag und löst OnClose aus, sodass ein späteres WriteData den Writer weiterhin erreicht. Verlassen Sie sich nicht darauf.

Threading. Der Schreibpfad hält keine eigene Sperre, serialisieren Sie daher Ihre eigenen Schreibvorgänge auf einem bestimmten Stream. Unterschiedliche Streams schreiben auf unterschiedliche QUIC-Streams und konkurrieren nicht miteinander.

.NET-Unterschied. Wenn kein Writer gebunden ist, verwirft das verwaltete WriteData die Daten stillschweigend, und der Quellcode sagt das ausdrücklich. Das Verhalten entspricht im Ergebnis dem von Delphi; nur der Mechanismus unterscheidet sich.

Beispiel


var
  oStream: TsgcWebTransportStream;
  vRaw: TBytes;
begin
  oStream := oSession.OpenStream(False);
  oStream.OnData := OnStreamData;      // assign BEFORE writing

  // Text: encoded to UTF-8 for you, with no framing added
  oStream.WriteData('Hello WebTransport');

  // Binary: written byte for byte
  vRaw := TEncoding.UTF8.GetBytes('{"action":"ping"}');
  oStream.WriteData(vRaw);
end;

// Framing: because OnData does NOT preserve message boundaries, a real
// protocol prefixes each message with its length and reassembles on receipt.
procedure TfrmClient.SendMessage(const aStream: TsgcWebTransportStream;
  const aMsg: string);
var
  vBody, vFrame: TBytes;
  vLen: Integer;
begin
  vBody := TEncoding.UTF8.GetBytes(aMsg);
  vLen := Length(vBody);

  SetLength(vFrame, 4 + vLen);
  vFrame[0] := Byte(vLen shr 24);
  vFrame[1] := Byte(vLen shr 16);
  vFrame[2] := Byte(vLen shr 8);
  vFrame[3] := Byte(vLen);
  if vLen > 0 then
    Move(vBody[0], vFrame[4], vLen);

  aStream.WriteData(vFrame);
end;

Zurück zu Methoden