sgcWebSockets in five minutes

You have installed the library and the palette is showing. This page takes you from there to a server that accepts a connection and a client that sends a message and reads the reply. Everything below is lifted from a demo that ships inside the download, so you can open the project instead of typing.

Delphi 7 to RAD Studio 13
Windows, Linux, macOS, iOS, Android
Client from Standard, server from Professional

What the first sample needs

Two non-visual components, one unit in the uses clause, and one extra unit for the event handler parameter types.

Client component

TsgcWebSocketClient, declared in sgcWebSocket.pas and registered on the SGC WebSockets palette page. Set Host, Port, then Active.

Server component

TsgcWebSocketServer, same unit, same palette page. Set Port, then Active. It listens, upgrades the handshake and raises OnConnect.

The second unit

Every event hands you a TsgcWSConnection, which lives in sgcWebSocket_Classes.pas. The demos write uses sgcWebSocket, sgcWebSocket_Classes; and so should you.

Platforms

Neither unit carries a platform guard, and both components are registered with ComponentPlatforms(0), so VCL, FMX, console and service targets all compile. A FireMonkey client demo ships in the box.

Requirements and editions

The edition column is the define that actually gates the code, with the line it sits on in Source/sgcVer.inc.

What Value
IDE Delphi 7 through RAD Studio 13, and C++Builder 2007 through 13. One package group per IDE version under Packages\.
Uses clause sgcWebSocket for the components, sgcWebSocket_Classes for TsgcWSConnection.
Client edition TsgcWebSocketClient is wrapped in {$IFDEF SGC_WS_CLIENT}. SGC_WS_CLIENT is defined on line 697, inside the {$IFDEF SGC_EDT_STD} block that runs from line 675 to line 724. So Standard and up.
Server edition TsgcWebSocketServer is wrapped in {$IFDEF SGC_EDT_PRO} directly, and its palette registration in sgcWebSocket_Reg.pas is inside the same guard. The Professional feature block runs from line 727 to line 758. So Professional and up. A Standard licence gives you the client, not the server.
Palette page Registered under {$IFDEF SGC_PACK_WEBSOCKETS}, defined on line 852.
Platforms No unit-scope platform guard in sgcWebSocket.pas, sgcWebSocket_Client.pas or sgcWebSocket_Server.pas. Windows brings in the Windows unit conditionally, nothing more.

Not sure which edition you are running? Open Source/sgcVer.inc and look at the first five lines. The SGC_EDT_* defines there are cumulative, so All-Access defines all of them and Standard defines only the first two.

Install and confirm the palette

Five steps from the zip to a component you can drop. Compile the runtime package before you install the design-time one, because the second references the first.

1. Unzip

Unzip the download to a folder of your choice. The rest of this page calls it {$DIR}. The Source\, Packages\, Demos\ and lib*\ folders are all under it.

2. Library path

Tools, Options, Library. Add {$DIR}\source and the folder that matches your IDE, for example {$DIR}\libD13\$(Platform) on RAD Studio 13 or {$DIR}\libD12\$(Platform) on 12.

3. Build the packages

Open {$DIR}\Packages\sgcWebSocketsD13.groupproj for your IDE version. Compile sgcWebSocketsD13.dpk first, then install dclsgcWebSocketsD13.dpk. C++Builder uses the .cbproj files in the same folder.

4. Check the palette

A new page called SGC WebSockets appears. On a Standard build it holds TsgcWebSocketClient. On Professional and up it also holds TsgcWebSocketServer, TsgcWebSocketHTTPServer, TsgcWebSocketProxyServer and TsgcWebSocketLoadBalancerServer.

5. Open a demo

Before writing anything, open {$DIR}\Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat. It is the smallest working pair in the library and the code below comes from it.

A server and a client, in about twenty lines

Start the server, start the client, send a string. The server tab listens on a port; the client tab connects to it and writes one message.

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;

Drop TsgcWebSocketServer on the form, name it WSServer, and let the IDE generate the four handlers from the Object Inspector. Connection.IP and Connection.WriteData both come from TsgcWSConnection, which is why sgcWebSocket_Classes is in the uses clause.

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;

Run the server project first, then this one. #connected appears in the client log and echo: Hello from Delphi comes back on OnMessage. That round trip is the whole quick start.

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.

The client runs its own thread, so a console program has to keep the main thread alive. That is what the Readln is for.

The server and client tabs are the shipped demo Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat, with the demo's checkbox and edit-box plumbing removed. The third tab is the same calls written against components created at runtime instead of dropped on a form.

Prove the round trip

Four events tell you everything about the first run, and you want all four wired before you go further.

Active

On the server, Active := True either succeeds or raises. If the port is taken you find out here rather than three steps later.

OnConnect

procedure(Connection: TsgcWSConnection). Fires on both sides. On the server, Connection.IP tells you who arrived; on the client it is the proof the handshake was upgraded.

OnMessage

procedure(Connection: TsgcWSConnection; const Text: string). The echo coming back on the client is the round trip proven end to end.

OnError and OnException

procedure(Connection: TsgcWSConnection; const Error: string) and procedure(Connection: TsgcWSConnection; E: Exception). Wire both. Without them a failure is silent and looks like nothing happened.

What usually goes wrong the first time

Almost every first-run problem is one of these six.

TsgcWebSocketServer is not on the palette

The server class is compiled only when SGC_EDT_PRO is defined, at sgcWebSocket.pas line 130, and registered only inside the same guard. On a Standard build the client is there and the server is not. That is licensing, not a broken install.

Undeclared identifier TsgcWSConnection

The components live in sgcWebSocket, the connection object lives in sgcWebSocket_Classes. Add the second unit to the uses clause. Every shipped demo has both.

The client connects, then drops

Set WatchDog.Enabled := True so a dropped connection reconnects on its own, and handle OnError and OnException. A silent disconnect with no handler looks like nothing happened.

Nothing arrives at the server

Check that the client is really up before writing. WriteData on an inactive client does nothing useful, which is why the demo tests if WSClient.Active then before sending.

Port already in use

Another instance of the server, or another program, still owns the port. Stop it, or move the server to a free port. The demo defaults are 5416 and 5418.

TLS fails on Linux or mobile

A wss:// connection needs a working TLS back end. Pick one through TLSOptions.IOHandler: OpenSSL everywhere, SChannel on Windows with no DLLs to deploy, or the native Apple and Android handlers in the Enterprise edition.

Where people go after the first message

The chat pair is the floor. These are the four directions the work usually takes, and all four are in the same library.

Speak a real protocol

The same client carries MQTT, AMQP, STOMP, Kafka and WAMP sub-protocol components. Drop one, point its Client property at your TsgcWebSocketClient, and you are on a broker.

sgcMQ quick start and the protocols overview

Serve HTTP as well as WebSockets

TsgcWebSocketHTTPServer answers ordinary HTTP requests and WebSocket upgrades on the same port, which is what you want when the browser has to fetch a page before it opens a socket.

HTTP components

Scale past one process

The Enterprise edition adds clustering, a load balancer server and a proxy server, so a single logical endpoint can sit in front of several server processes.

Cluster reference and load balancer reference

Harden it before it ships

Rate limiting, a circuit breaker, an API key manager and a firewall component all attach to the server you already have.

Rate limiter, circuit breaker and firewall

Reference, demos and documentation

The reference pages document every property and event. The demo projects are inside your download, under Demos\01.WebSocket_Quick_Start.

Reference, WebSocket client Every property, method and event on TsgcWebSocketClient.
Reference, WebSocket server Bindings, authentication, broadcasting and connection management on TsgcWebSocketServer.
Online help, TsgcWebSocketClient The generated component reference, always in step with the current release.
Which edition do I need Feature by feature, what Standard, Professional, Enterprise and All-Access each turn on.
Download the trial The same installer as production, time limited, one per IDE version.
User manual (PDF) The full manual covering every component in the library.

Related reading: what WebSockets actually are, the client connect and watchdog events, and securing a WebSocket server. Every product has its own quick start, listed on the getting started page.

sgcWebSockets quick start questions

sgcWebSocket gives you TsgcWebSocketClient and TsgcWebSocketServer. Add sgcWebSocket_Classes as well, because every event hands you a TsgcWSConnection and that type is declared there. The shipped demos write uses sgcWebSocket, sgcWebSocket_Classes; and the server demo adds sgcWebSocket_Server.
The server class is compiled inside {$IFDEF SGC_EDT_PRO}, and its palette registration in sgcWebSocket_Reg.pas sits inside the same guard. SGC_EDT_PRO turns on the Professional feature block, lines 727 to 758 of sgcVer.inc. A Standard build compiles the client only. The client define, SGC_WS_CLIENT, is on line 697 inside the Standard block, lines 675 to 724.
They come from sgcWebSocket_Classes.pas. OnConnect is procedure(Connection: TsgcWSConnection). OnDisconnect is procedure(Connection: TsgcWSConnection; Code: Integer). OnMessage is procedure(Connection: TsgcWSConnection; const Text: string). OnError is procedure(Connection: TsgcWSConnection; const Error: string). OnException is procedure(Connection: TsgcWSConnection; E: Exception). Let the IDE generate them rather than typing them, because an extra or missing parameter is the most common compile error on a first project.
Yes. sgcWebSocket.pas, sgcWebSocket_Client.pas and sgcWebSocket_Server.pas carry no unit-scope platform guard, and both components are registered with ComponentPlatforms(0), so the IDE does not restrict them to a target. A FireMonkey client and server demo ships under Demos\01.WebSocket_Quick_Start\07.Firemonkey_Server_and_Client. The only platform-restricted WebSocket component in the library is TsgcWebSocketClient_WinHTTP, which is Win32 and Win64.
Set TLS := True on the client and point Port at the TLS port. Then choose a TLS back end with TLSOptions.IOHandler. OpenSSL works everywhere and needs libcrypto-3.dll and libssl-3.dll beside the executable on Windows. SChannel is Windows only and ships nothing extra. The native Apple and Android handlers are Enterprise features.
Yes, and the third tab above does exactly that. Assign the event handlers before you set Active := True, otherwise the first OnConnect can fire before your handler is attached. In a console application remember that the client runs its own thread, so the main thread has to stay alive, which is why the sample ends with Readln.
It reconnects a client that has dropped, on an interval you choose. Turn it on for anything long running, because a network hiccup that closes the socket will otherwise leave your application silently disconnected. Set WatchDog.Enabled := True and, if the default is too eager, WatchDog.Interval and WatchDog.Attempts.
Inside your download, under Demos\. The pair used on this page is 01.WebSocket_Quick_Start\01.Server_and_Client_Chat. Also worth opening early: 06.Authentication for a server that checks credentials, 07.Firemonkey_Server_and_Client for a cross-platform client, and 12.Groups for broadcasting to a subset of connections.
Best value: All-AccessEvery eSeGeCe product, Premium Support included, from €1,059/year.
See All-Access pricing

Ready to build on it?

Download the trial and run the chat demo before you write a line of your own.