TsgcWebTransportSession › Ereignisse › OnStream
Wird ausgelöst, wenn der Peer einen neuen Stream innerhalb dieser Sitzung öffnet. Weisen Sie hier OnData auf dem Stream zu, andernfalls gehen die ersten Bytes verloren.
property OnStream: TsgcWebTransportStreamEvent read FOnStream write FOnStream;
// event type
TsgcWebTransportStreamEvent = procedure(Sender: TObject;
const aStream: TsgcWebTransportStream) of object;
// handler signature
procedure MyStream(Sender: TObject; const aStream: TsgcWebTransportStream);
| Name | Typ | Beschreibung |
|---|---|---|
Sender | TObject | Die TsgcWebTransportSession, zu der der Stream gehört. Dasselbe Objekt wie aStream.Session. |
aStream | const TsgcWebTransportStream | Der neue Stream, vollständig registriert, bevor das Ereignis ausgelöst wird. StreamId, Unidirectional und Session sind bereits gesetzt, und HeaderSent ist True, weil der Peer den Header gesendet hat. Er gehört der Sitzung, geben Sie ihn also nicht frei. |
Nicht zugewiesen. Wenn kein Handler zugewiesen ist, werden vom Peer geöffnete Streams weiterhin registriert und gezählt, Sie erfahren jedoch nie davon, und alle darin übertragenen Daten werden verworfen.
Wann es ausgelöst wird. Der Transport liest einen brandneuen QUIC-Stream, findet darauf einen WebTransport-Header, varint(0x54) für unidirektional oder varint(0x41) für bidirektional, gefolgt von varint(SessionId), und ordnet diese Session-ID dieser Sitzung zu. Anschließend ruft er AddIncomingStream auf, was den Stream registriert und dieses Ereignis auslöst.
Weisen Sie OnData innerhalb des Handlers zu. Das ist der wichtige Punkt. Bytes, die im selben Lesevorgang wie der Header eingetroffen sind, werden unmittelbar nach der Rückkehr Ihres Handlers an OnData des Streams zugestellt. Wenn Sie OnData bis dahin nicht zugewiesen haben, sind diese Bytes verloren, ohne Fehlermeldung. Da ein Peer seinen Header und seine erste Nachricht typischerweise zusammen schreibt, ist das der Normalfall und kein Sonderfall. Weisen Sie zuerst den Handler zu, alles Weitere danach.
Antworten auf dem Stream. Bei einem bidirektionalen Stream binden der HTTP/3-Client und der Server unmittelbar nach der Registrierung einen Writer pro Stream, sodass aStream.WriteData auf demselben QUIC-Stream antwortet. Vom Peer geöffnete unidirektionale Streams dienen ausschließlich dem Empfang; das Schreiben auf einen solchen Stream ist sinnlos, prüfen Sie daher Unidirectional, bevor Sie antworten.
Weisen Sie OnStream früh genug zu. Weisen Sie es auf dem Server innerhalb von OnWebTransportSession zu, bevor dieser Handler zurückkehrt, da der Peer einen Stream öffnen kann, sobald er den :status = 200 sieht. Weisen Sie es auf dem Client unmittelbar nach der Rückkehr von WebTransportConnect zu und bevor Sie mit dem Pumpen beginnen.
Threading. In Delphi und C++Builder läuft das Ereignis auf dem Thread, der die Verbindung pumpt: auf dem Client der Thread, der WebTransportProcessEvents aufruft, auf dem Server ein Verbindungsthread des Servers. Es wird nicht mit dem Haupt-Thread synchronisiert, führen Sie UI-Arbeit daher selbst per Marshalling aus. Unter .NET läuft es auf einem Thread-Pool-Thread der eingehenden Accept-Schleife.
Der Stream befindet sich bereits in der Liste der Sitzung, wenn das Ereignis ausgelöst wird, StreamCount zählt ihn also mit und FindStreamById findet ihn aus Ihrem Handler heraus.
// Server: assign OnStream while accepting, before the handler returns
procedure TfrmServer.OnWTSession(Sender: TObject;
const aConnection: TsgcQUICServerConnection;
const aSession: TsgcWebTransportSession; var aAccept: Boolean);
begin
aAccept := True;
aSession.OnStream := OnWTStream; // peer may open a stream at once
end;
procedure TfrmServer.OnWTStream(Sender: TObject;
const aStream: TsgcWebTransportStream);
begin
// FIRST: hook OnData. Bytes that came with the header are delivered
// as soon as this handler returns, and would otherwise be lost.
aStream.OnData := OnWTStreamData;
aStream.OnClose := OnWTStreamClose;
memoLog.Lines.Add(Format('stream %d opened by peer (%s)',
[aStream.StreamId,
BoolToStr(aStream.Unidirectional, True)]));
end;
procedure TfrmServer.OnWTStreamData(Sender: TObject; const aData: TBytes);
var
oStream: TsgcWebTransportStream;
begin
if not (Sender is TsgcWebTransportStream) then
Exit;
oStream := TsgcWebTransportStream(Sender);
memoLog.Lines.Add('received: ' + TEncoding.UTF8.GetString(aData));
// Echo back, but only on a bidirectional stream
if not oStream.Unidirectional then
oStream.WriteData(aData);
end;