sgcWebSockets in fünf Minuten

Du hast die Bibliothek installiert und die Palette wird angezeigt. Diese Seite führt dich von dort zu einem Server, der eine Verbindung annimmt, und einem Client, der eine Nachricht sendet und die Antwort liest. Alles Folgende stammt aus einer Demo, die im Download enthalten ist, du kannst also das Projekt öffnen, statt zu tippen.

Delphi 7 bis RAD Studio 13
Windows, Linux, macOS, iOS, Android
Client ab Standard, Server ab Professional

Was das erste Beispiel benötigt

Zwei nicht visuelle Komponenten, eine Unit in der Uses-Klausel und eine weitere Unit für die Parametertypen der Ereignisbehandler.

Client-Komponente

TsgcWebSocketClient, deklariert in sgcWebSocket.pas und auf der Palettenseite SGC WebSockets registriert. Setze Host, Port und danach Active.

Server-Komponente

TsgcWebSocketServer, gleiche Unit, gleiche Palettenseite. Setze Port und danach Active. Der Server lauscht, führt das Handshake-Upgrade durch und löst OnConnect aus.

Die zweite Unit

Jedes Ereignis übergibt dir ein TsgcWSConnection, das in sgcWebSocket_Classes.pas liegt. Die Demos schreiben uses sgcWebSocket, sgcWebSocket_Classes; und du solltest das auch tun.

Plattformen

Keine der beiden Units enthält einen Plattform-Guard und beide Komponenten sind mit ComponentPlatforms(0) registriert, daher lassen sich VCL-, FMX-, Konsolen- und Dienst-Ziele kompilieren. Eine FireMonkey-Client-Demo liegt dem Download bei.

Voraussetzungen und Editionen

Die Editionsspalte nennt das Define, das den Code tatsächlich steuert, samt der Zeile in Source/sgcVer.inc, in der es steht.

Was Wert
IDE Delphi 7 bis RAD Studio 13 sowie C++Builder 2007 bis 13. Pro IDE-Version gibt es eine Paketgruppe unter Packages\.
Uses-Klausel sgcWebSocket für die Komponenten, sgcWebSocket_Classes für TsgcWSConnection.
Client-Edition TsgcWebSocketClient ist in {$IFDEF SGC_WS_CLIENT} eingeschlossen. SGC_WS_CLIENT wird in Zeile 697 definiert, innerhalb des Blocks {$IFDEF SGC_EDT_STD}, der von Zeile 675 bis Zeile 724 reicht. Also Standard und höher.
Server-Edition TsgcWebSocketServer ist direkt in {$IFDEF SGC_EDT_PRO} eingeschlossen, und seine Palettenregistrierung in sgcWebSocket_Reg.pas liegt im selben Guard. Der Funktionsblock Professional reicht von Zeile 727 bis Zeile 758. Also Professional und höher. Eine Standard-Lizenz liefert dir den Client, nicht den Server.
Palettenseite Registriert unter {$IFDEF SGC_PACK_WEBSOCKETS}, definiert in Zeile 852.
Plattformen Kein Plattform-Guard auf Unit-Ebene in sgcWebSocket.pas, sgcWebSocket_Client.pas oder sgcWebSocket_Server.pas. Unter Windows wird lediglich die Unit Windows bedingt eingebunden, mehr nicht.

Du bist nicht sicher, welche Edition du verwendest? Öffne Source/sgcVer.inc und sieh dir die ersten fünf Zeilen an. Die SGC_EDT_*-Defines dort sind kumulativ: All-Access definiert alle, Standard nur die ersten beiden.

Installieren und die Palette prüfen

Fünf Schritte vom Zip-Archiv bis zu einer Komponente, die du platzieren kannst. Kompiliere das Laufzeitpaket, bevor du das Entwurfszeitpaket installierst, denn Letzteres verweist auf Ersteres.

1. Entpacken

Entpacke den Download in einen Ordner deiner Wahl. Der Rest dieser Seite nennt ihn {$DIR}. Die Ordner Source\, Packages\, Demos\ und lib*\ liegen alle darunter.

2. Bibliothekspfad

Tools, Optionen, Bibliothek. Füge {$DIR}\source und den Ordner hinzu, der zu deiner IDE passt, zum Beispiel {$DIR}\libD13\$(Platform) bei RAD Studio 13 oder {$DIR}\libD12\$(Platform) bei 12.

3. Pakete erstellen

Öffne {$DIR}\Packages\sgcWebSocketsD13.groupproj für deine IDE-Version. Kompiliere zuerst sgcWebSocketsD13.dpk und installiere dann dclsgcWebSocketsD13.dpk. C++Builder verwendet die .cbproj-Dateien im selben Ordner.

4. Palette prüfen

Es erscheint eine neue Seite namens SGC WebSockets. In einem Standard-Build enthält sie TsgcWebSocketClient. Ab Professional enthält sie zusätzlich TsgcWebSocketServer, TsgcWebSocketHTTPServer, TsgcWebSocketProxyServer und TsgcWebSocketLoadBalancerServer.

5. Eine Demo öffnen

Bevor du etwas schreibst, öffne {$DIR}\Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat. Es ist das kleinste funktionierende Paar der Bibliothek, und der Code unten stammt daraus.

Ein Server und ein Client in etwa zwanzig Zeilen

Starte den Server, starte den Client, sende einen String. Der Server-Tab lauscht auf einem Port, der Client-Tab verbindet sich damit und schreibt eine Nachricht.

uServerChat.pas
uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

procedure TfrmServerChat.btnStartClick(Sender: TObject);
begin
  WSServer.Port := 5418;
  WSServer.Active := True;
  memoLog.Lines.Add('#started');
end;

procedure TfrmServerChat.WSServerConnect(Connection: TsgcWSConnection);
begin
  memoLog.Lines.Add('Connected: ' + Connection.IP);
end;

procedure TfrmServerChat.WSServerDisconnect(Connection: TsgcWSConnection;
  Code: Integer);
begin
  memoLog.Lines.Add('Disconnected (' + IntToStr(Code) + '): ' + Connection.IP);
end;

procedure TfrmServerChat.WSServerMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  memoLog.Lines.Add(Text);
  // send it straight back, so the client has something to read
  Connection.WriteData('echo: ' + Text);
end;

Platziere TsgcWebSocketServer auf dem Formular, nenne ihn WSServer und lass die IDE die vier Handler im Objektinspektor generieren. Connection.IP und Connection.WriteData stammen beide aus TsgcWSConnection, deshalb steht sgcWebSocket_Classes in der Uses-Klausel.

uClientChat.pas
uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

procedure TfrmClientChat.btnStartClick(Sender: TObject);
begin
  WSClient.Host := 'localhost';
  WSClient.Port := 5418;
  WSClient.TLS := False;
  WSClient.Active := True;
end;

procedure TfrmClientChat.btnSendClick(Sender: TObject);
begin
  if WSClient.Active then
    WSClient.WriteData('Hello from Delphi')
  else
    raise Exception.Create('Not connected');
end;

procedure TfrmClientChat.WSClientConnect(Connection: TsgcWSConnection);
begin
  memoLog.Lines.Add('#connected');
end;

procedure TfrmClientChat.WSClientMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  memoLog.Lines.Add(Text);
end;

Starte zuerst das Server-Projekt, dann dieses. #connected erscheint im Client-Log und echo: Hello from Delphi kommt über OnMessage zurück. Diese Hin-und-zurück-Runde ist der gesamte Schnellstart.

uConsole.pas
program WSConsoleClient;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

type
  TChatHandler = class
    procedure DoConnect(Connection: TsgcWSConnection);
    procedure DoMessage(Connection: TsgcWSConnection; const Text: string);
  end;

procedure TChatHandler.DoConnect(Connection: TsgcWSConnection);
begin
  Writeln('#connected');
end;

procedure TChatHandler.DoMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  Writeln('Server says: ', Text);
end;

var
  oClient: TsgcWebSocketClient;
  oHandler: TChatHandler;
begin
  oHandler := TChatHandler.Create;
  oClient := TsgcWebSocketClient.Create(nil);
  try
    oClient.Host := 'localhost';
    oClient.Port := 5418;
    oClient.WatchDog.Enabled := True;   // reconnect on its own

    // assign the handlers BEFORE Active, or the first
    // OnConnect can fire with nothing attached
    oClient.OnConnect := oHandler.DoConnect;
    oClient.OnMessage := oHandler.DoMessage;

    oClient.Active := True;
    oClient.WriteData('Hello from Delphi');
    Readln;
  finally
    oClient.Free;
    oHandler.Free;
  end;
end.

Der Client läuft in einem eigenen Thread, daher muss ein Konsolenprogramm den Haupt-Thread am Leben halten. Genau dafür ist das Readln da.

Die Tabs Server und Client entsprechen der mitgelieferten Demo Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat, ohne die Checkbox- und Eingabefeld-Logik der Demo. Der dritte Tab enthält dieselben Aufrufe, geschrieben für Komponenten, die zur Laufzeit erstellt statt auf ein Formular gezogen werden.

Die Hin-und-zurück-Runde belegen

Vier Ereignisse verraten dir alles über den ersten Lauf, und du solltest alle vier verdrahten, bevor du weitermachst.

Active

Auf dem Server gelingt Active := True entweder oder löst eine Exception aus. Wenn der Port belegt ist, erfährst du es hier und nicht erst drei Schritte später.

OnConnect

procedure(Connection: TsgcWSConnection). Wird auf beiden Seiten ausgelöst. Auf dem Server sagt dir Connection.IP, wer sich verbunden hat, auf dem Client ist es der Beleg, dass der Handshake aufgewertet wurde.

OnMessage

procedure(Connection: TsgcWSConnection; const Text: string). Das Echo, das beim Client ankommt, belegt die Hin-und-zurück-Runde von Ende zu Ende.

OnError und OnException

procedure(Connection: TsgcWSConnection; const Error: string) und procedure(Connection: TsgcWSConnection; E: Exception). Verdrahte beide. Ohne sie bleibt ein Fehler stumm und es sieht aus, als wäre nichts passiert.

Was beim ersten Mal meistens schiefgeht

Fast jedes Problem beim ersten Start ist eines dieser sechs.

TsgcWebSocketServer fehlt in der Palette

Die Server-Klasse wird nur kompiliert, wenn SGC_EDT_PRO definiert ist, in sgcWebSocket.pas Zeile 130, und nur innerhalb desselben Guards registriert. In einem Standard-Build ist der Client vorhanden und der Server nicht. Das ist Lizenzierung, keine defekte Installation.

Nicht deklarierter Bezeichner TsgcWSConnection

Die Komponenten liegen in sgcWebSocket, das Verbindungsobjekt liegt in sgcWebSocket_Classes. Füge die zweite Unit zur Uses-Klausel hinzu. Jede mitgelieferte Demo enthält beide.

Der Client verbindet sich und bricht dann ab

Setze WatchDog.Enabled := True, damit eine unterbrochene Verbindung sich selbstständig wieder aufbaut, und behandle OnError und OnException. Eine stille Trennung ohne Handler sieht aus, als wäre nichts passiert.

Beim Server kommt nichts an

Prüfe, ob der Client wirklich verbunden ist, bevor du schreibst. WriteData auf einem inaktiven Client bewirkt nichts Sinnvolles, weshalb die Demo vor dem Senden if WSClient.Active then abfragt.

Port bereits belegt

Eine andere Instanz des Servers oder ein anderes Programm hält den Port noch. Beende sie oder verschiebe den Server auf einen freien Port. Die Standardwerte der Demo sind 5416 und 5418.

TLS schlägt unter Linux oder mobil fehl

Eine wss://-Verbindung braucht ein funktionierendes TLS-Backend. Wähle eines über TLSOptions.IOHandler: OpenSSL überall, SChannel unter Windows ohne DLLs zum Ausliefern, oder die nativen Apple- und Android-Handler in der Enterprise-Edition.

Wohin es nach der ersten Nachricht weitergeht

Das Chat-Paar ist die Grundlage. Das sind die vier Richtungen, in die die Arbeit meist geht, und alle vier gehören zur selben Bibliothek.

Ein echtes Protokoll sprechen

Derselbe Client trägt die Sub-Protokoll-Komponenten für MQTT, AMQP, STOMP, Kafka und WAMP. Platziere eine, setze ihre Eigenschaft Client auf deinen TsgcWebSocketClient, und du bist an einem Broker.

sgcMQ-Schnellstart und die Protokollübersicht

HTTP und WebSockets gemeinsam bereitstellen

TsgcWebSocketHTTPServer beantwortet gewöhnliche HTTP-Anfragen und WebSocket-Upgrades auf demselben Port. Genau das brauchst du, wenn der Browser erst eine Seite laden muss, bevor er einen Socket öffnet.

HTTP-Komponenten

Über einen Prozess hinaus skalieren

Die Enterprise-Edition ergänzt Clustering, einen Load-Balancer-Server und einen Proxy-Server, sodass ein einzelner logischer Endpunkt vor mehreren Serverprozessen stehen kann.

Cluster-Referenz und Load-Balancer-Referenz

Vor der Auslieferung absichern

Rate Limiting, ein Circuit Breaker, eine API-Schlüsselverwaltung und eine Firewall-Komponente lassen sich alle an den Server anhängen, den du bereits hast.

Rate Limiter, Circuit Breaker und Firewall

Referenz, Demos und Dokumentation

Die Referenzseiten dokumentieren jede Eigenschaft und jedes Ereignis. Die Demo-Projekte liegen in deinem Download unter Demos\01.WebSocket_Quick_Start.

Referenz, WebSocket-Client Jede Eigenschaft, Methode und jedes Ereignis von TsgcWebSocketClient.
Referenz, WebSocket-Server Bindungen, Authentifizierung, Broadcasting und Verbindungsverwaltung in TsgcWebSocketServer.
Online-Hilfe, TsgcWebSocketClient Die generierte Komponentenreferenz, stets auf dem Stand der aktuellen Version.
Welche Edition brauche ich Funktion für Funktion, was Standard, Professional, Enterprise und All-Access jeweils freischalten.
Testversion herunterladen Derselbe Installer wie in der Vollversion, zeitlich begrenzt, eine pro IDE-Version.
Benutzerhandbuch (PDF) Das vollständige Handbuch zu jeder Komponente der Bibliothek.

Zum Weiterlesen: was WebSockets eigentlich sind, die Client-Ereignisse für Verbindungsaufbau und Watchdog und einen WebSocket-Server absichern. Jedes Produkt hat einen eigenen Schnellstart, aufgelistet auf der Seite Erste Schritte.

Fragen zum sgcWebSockets-Schnellstart

sgcWebSocket liefert dir TsgcWebSocketClient und TsgcWebSocketServer. Füge zusätzlich sgcWebSocket_Classes hinzu, denn jedes Ereignis übergibt dir ein TsgcWSConnection, und dieser Typ ist dort deklariert. Die mitgelieferten Demos schreiben uses sgcWebSocket, sgcWebSocket_Classes; und die Server-Demo ergänzt sgcWebSocket_Server.
Die Server-Klasse wird innerhalb von {$IFDEF SGC_EDT_PRO} kompiliert, und ihre Palettenregistrierung in sgcWebSocket_Reg.pas liegt im selben Guard. SGC_EDT_PRO aktiviert den Professional-Funktionsblock, Zeilen 727 bis 758 von sgcVer.inc. Ein Standard-Build kompiliert nur den Client. Das Client-Define SGC_WS_CLIENT steht in Zeile 697 innerhalb des Standard-Blocks, Zeilen 675 bis 724.
Sie stammen aus sgcWebSocket_Classes.pas. OnConnect ist procedure(Connection: TsgcWSConnection). OnDisconnect ist procedure(Connection: TsgcWSConnection; Code: Integer). OnMessage ist procedure(Connection: TsgcWSConnection; const Text: string). OnError ist procedure(Connection: TsgcWSConnection; const Error: string). OnException ist procedure(Connection: TsgcWSConnection; E: Exception). Lass sie von der IDE generieren, statt sie zu tippen, denn ein überzähliger oder fehlender Parameter ist der häufigste Compilerfehler in einem ersten Projekt.
Ja. sgcWebSocket.pas, sgcWebSocket_Client.pas und sgcWebSocket_Server.pas enthalten keinen Plattform-Guard auf Unit-Ebene, und beide Komponenten sind mit ComponentPlatforms(0) registriert, sodass die IDE sie auf kein Ziel beschränkt. Eine FireMonkey-Client- und Server-Demo liegt unter Demos\01.WebSocket_Quick_Start\07.Firemonkey_Server_and_Client. Die einzige plattformbeschränkte WebSocket-Komponente der Bibliothek ist TsgcWebSocketClient_WinHTTP, die für Win32 und Win64 gilt.
Setze TLS := True auf dem Client und richte Port auf den TLS-Port. Wähle dann ein TLS-Backend mit TLSOptions.IOHandler. OpenSSL funktioniert überall und braucht unter Windows libcrypto-3.dll und libssl-3.dll neben der ausführbaren Datei. SChannel gibt es nur unter Windows und es muss nichts zusätzlich ausgeliefert werden. Die nativen Apple- und Android-Handler sind Enterprise-Funktionen.
Ja, und der dritte Tab oben macht genau das. Weise die Ereignisbehandler zu, bevor du Active := True setzt, sonst kann das erste OnConnect ausgelöst werden, bevor dein Handler angehängt ist. Denk in einer Konsolenanwendung daran, dass der Client in einem eigenen Thread läuft und der Haupt-Thread deshalb am Leben bleiben muss, weshalb das Beispiel mit Readln endet.
Er verbindet einen getrennten Client in einem von dir gewählten Intervall erneut. Schalte ihn für alles Langlaufende ein, denn ein Netzwerkaussetzer, der den Socket schließt, lässt deine Anwendung sonst stillschweigend getrennt zurück. Setze WatchDog.Enabled := True und, falls der Standardwert zu eifrig ist, WatchDog.Interval und WatchDog.Attempts.
In deinem Download unter Demos\. Das Paar, das auf dieser Seite verwendet wird, ist 01.WebSocket_Quick_Start\01.Server_and_Client_Chat. Ebenfalls früh einen Blick wert: 06.Authentication für einen Server, der Zugangsdaten prüft, 07.Firemonkey_Server_and_Client für einen plattformübergreifenden Client und 12.Groups für Broadcasting an eine Teilmenge der Verbindungen.
Bestes Preis-Leistungs-Verhältnis: All-AccessAlle eSeGeCe-Produkte, inklusive Premium-Support, ab €1,059 pro Jahr.
All-Access-Preise ansehen

Bereit, darauf aufzubauen?

Lade die Testversion herunter und starte die Chat-Demo, bevor du eine eigene Zeile schreibst.