Komponenty klienta i serwera QUIC dla Delphi i C++ Builder | eSeGeCe Blog

Komponenty klienta i serwera QUIC dla Delphi i C++ Builder

· Komponenty
Komponenty klienta i serwera QUIC sgcQUIC

sgcQUIC wprowadza protokół transportowy QUIC (RFC 9000) do Delphi, C++ Builder i .NET. Dostarcza dwa nowe komponenty, TsgcQUICClient i TsgcQUICServer, oba zbudowane na natywnym silniku QUIC w OpenSSL 3.5, więc transport i uzgadnianie TLS 1.3 przebiegają w jednej wymianie.

QUIC to protokół leżący u podstaw HTTP/3, ale jest przydatny również sam w sobie. Działa poprzez UDP, multipleksuje wiele niezależnych strumieni w jednym połączeniu, wznawia się dzięki 0-RTT i przetrwa zmianę sieci dzięki migracji połączenia. Ten wpis dotyczy surowej warstwy QUIC. Następny wpis omawia komponenty HTTP/3, które są zbudowane ponad nią.

Dlaczego QUIC

Klasyczne połączenie TLS-over-TCP wymaga uzgadniania TCP, a następnie uzgadniania TLS, zanim przemieści się pierwszy bajt danych aplikacji. QUIC łączy oba w jedną wymianę, więc nowe połączenie jest gotowe w ramach jednej rundy komunikacji, a wznowione może wysyłać dane dzięki 0-RTT.

Ponieważ każdy strumień QUIC jest dostarczany niezależnie, utracony pakiet w jednym strumieniu nie blokuje pozostałych. To eliminuje blokowanie na początku kolejki (head-of-line blocking), które występuje przy multipleksowaniu na jednym gnieździe TCP. Połączenie QUIC jest identyfikowane przez identyfikator połączenia, a nie przez parę adresu IP i portu, więc może migrować z Wi-Fi do danych mobilnych bez zrywania.

Klient QUIC

Ustaw Host i Port, przypisz zdarzenia, a następnie ustaw Active na True. Uzgadnianie kończy się w jednej wymianie, a WriteData wysyła bajty w strumieniu QUIC.

uses
  sgcQUIC_Client;

var
  oClient: TsgcQUICClient;
begin
  oClient := TsgcQUICClient.Create(nil);
  oClient.Host := 'www.example.com';
  oClient.Port := 443;
  oClient.OnQUICConnect    := OnQUICConnect;
  oClient.OnQUICStreamData := OnQUICStreamData;
  oClient.OnQUICDisconnect := OnQUICDisconnect;

  oClient.Active := True;          // TLS 1.3 handshake in a single flight
  oClient.WriteData('ping');       // send bytes on a QUIC stream
end;

Przychodzące bajty pojawiają się w zdarzeniu OnQUICStreamData, które przekazuje identyfikator strumienia oraz ładunek danych:

procedure TForm1.OnQUICStreamData(Sender: TObject; aStreamId: Int64;
  aUnidirectional: Boolean; const aData: TBytes);
begin
  Memo1.Lines.Add('stream ' + IntToStr(aStreamId) + ': ' +
    TEncoding.UTF8.GetString(aData));
end;

Serwer QUIC

Serwer nasłuchuje na porcie UDP i potrzebuje certyfikatu oraz klucza prywatnego w formacie PEM. QUIC zawsze działa na TLS 1.3, więc certyfikat jest obowiązkowy. Bajty od klienta pojawiają się w OnQUICData, a odpowiadasz za pomocą WriteData, przekazując połączenie, na które chcesz odpowiedzieć.

uses
  sgcQUIC_Server;

var
  oServer: TsgcQUICServer;
begin
  oServer := TsgcQUICServer.Create(nil);
  oServer.Port := 443;
  oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
  oServer.QUICOptions.SSLOptions.KeyFile  := 'key.pem';
  oServer.OnQUICConnect := OnQUICConnect;
  oServer.OnQUICData    := OnQUICData;
  oServer.Active := True;
end;

procedure TForm1.OnQUICData(Sender: TObject;
  aConnection: TsgcQUICServerConnection; const aData: TBytes);
begin
  // echo the message back to the client that sent it
  oServer.WriteData(aConnection, aData);
end;

Multipleksowane strumienie

Pojedyncze połączenie QUIC może przenosić wiele strumieni jednocześnie. Wywołaj EnableMultiStream przed połączeniem, a następnie otwórz tyle strumieni, ile potrzebujesz. Strumień dwukierunkowy przenosi żądanie i jego odpowiedź; strumień jednokierunkowy przesyła dane w jedną stronę.

oClient.EnableMultiStream;
oClient.OpenStream;                 // a new bidirectional stream
oClient.OpenStream(True);           // a unidirectional stream

Tryb wielu strumieni korzysta z wbudowanego silnika QUIC OpenSSL 3.5. Każdy strumień ma własną kontrolę przepływu, więc powolny lub zablokowany strumień nigdy nie blokuje pozostałych.

0-RTT i migracja połączenia

Po pierwszym udanym uzgadnianiu klient może zachować bilet sesji i ponownie połączyć się z 0-RTT, wysyłając dane aplikacji już w pierwszym pakiecie. Migracja połączenia utrzymuje sesję przy życiu podczas zmiany sieci, co ma znaczenie dla klientów mobilnych przemieszczających się między Wi-Fi a siecią komórkową. Obie funkcje są obsługiwane przez leżący u podstaw silnik QUIC.

Dostępność

sgcQUIC to osobny pakiet, licencjonowany jako dodatek do sgcWebSockets Enterprise. Każda licencja zawiera pełny kod źródłowy w języku Pascal oraz rok aktualizacji. Komponenty instalują się na palecie SGC QUIC i obsługują Delphi oraz C++ Builder od wersji 7 do 13, a także port .NET z tymi samymi nazwami klas Tsgc.

Komponenty klienta i serwera HTTP/3 są omówione w następnym wpisie. Możesz pobrać wersję próbną i przeczytać pełną dokumentację komponentów na stronie produktu sgcQUIC.

Masz pytania lub uwagi? Skontaktuj się z nami, otrzymasz odpowiedź od osób, które napisały ten kod.