sgcWebSockets Message Brokers
These eight components speak the wire protocols of the common message brokers.
They are not standalone clients. Each one attaches to a TsgcWebSocketClient,
which owns the socket, the TLS, the reconnect and the heartbeat. Get that
relationship right and the rest follows.
When to use this skill
- Publish to or subscribe from an MQTT broker (Mosquitto, HiveMQ, EMQX, AWS IoT)
- Talk STOMP to RabbitMQ, ActiveMQ or any STOMP broker
- Use AMQP 0.9.1 against RabbitMQ, or AMQP 1.0 against Azure Service Bus
- Produce to and consume from Kafka
- Use WAMP2 for publish/subscribe plus remote procedure calls
For the sgc built-in subprotocols (broker, dataset, files, presence, WAMP1,
E2EE) load sgcwebsockets-protocols. For the AWS IoT and Azure IoT wrappers,
which are MQTT with the cloud specifics already filled in, load
sgcwebsockets-iot.
Install and uses clause
All eight live in one unit. You also need the transport client and the connection class:
uses
sgcWebSocket, // TsgcWebSocketClient, the transport
sgcWebSocket_Protocols, // the protocol components in this skill
sgcWebSocket_Classes, // TsgcWSConnection, handed to every event
sgcWebSocket_Types; // TmqttQoS and the other enumerations
The binding rule, read this before writing any code
A protocol component does nothing until you assign a transport:
MQTT.Client := WSClient;
Two consequences that cause most of the confusion:
One protocol per client. A TsgcWebSocketClient carries one protocol at a
time. If you have several protocol components on a form, set the ones you are
not using to nil before binding the one you want. Leaving two bound to the
same client produces a handshake that neither broker accepts.
STOMP.Client := nil;
KAFKA.Client := nil;
MQTT.Client := WSClient;
The transport is a switch on the client, not the protocol. MQTT and STOMP run either over a raw TCP socket or inside a WebSocket frame, and brokers differ in which they expose, usually on different ports:
WSClient.Specifications.RFC6455 := False; // raw TCP, the usual broker port
WSClient.Specifications.RFC6455 := True; // MQTT over WebSocket
Connecting a raw-TCP client to a WebSocket endpoint fails at the handshake with an error that does not mention the transport, so check this first when a broker refuses you.
Before you start, ask the developer
Use a structured question tool if your host has one, for example Claude Code's
AskUserQuestion. Otherwise ask in chat. These change the code you write:
- Which broker and which protocol? RabbitMQ speaks AMQP 0.9.1, STOMP and MQTT. Azure Service Bus speaks AMQP 1.0. They are different components, and AMQP 0.9.1 and AMQP 1.0 are unrelated protocols despite the name.
- Raw TCP or over WebSocket? Sets
Specifications.RFC6455and the port. - TLS? Broker TLS ports differ from plaintext ones, 8883 against 1883 for MQTT for instance.
- Which MQTT version?
MQTTVersionselects 3.1.1 or 5.0. Version 5 adds the properties parameters that appear throughout the API. - What delivery guarantee? QoS 0, 1 or 2 changes both the publish call and which acknowledgement events you need to handle.
Components in this skill
| Component | Protocol | Shape of the API |
|---|---|---|
TsgcWSPClient_MQTT |
MQTT 3.1.1 and 5.0 | Publish, Subscribe, event driven |
TsgcWSPClient_STOMP |
STOMP | Send, Subscribe, ACK, transactions |
TsgcWSPClient_STOMP_RabbitMQ |
STOMP | RabbitMQ specifics on top of STOMP |
TsgcWSPClient_STOMP_ActiveMQ |
STOMP | ActiveMQ specifics on top of STOMP |
TsgcWSPClient_AMQP |
AMQP 0.9.1 | channels: OpenChannel, exchanges, queues |
TsgcWSPClient_AMQP1 |
AMQP 1.0 | sessions and links, Azure CBS token helpers |
TsgcWSPClient_Kafka |
Kafka | Produce, Subscribe, Poll, CommitSync |
TsgcWSPClient_WAMP2 |
WAMP2 | Publish/Subscribe plus Call/RegisterCall |
Kafka is the odd one out. It is a poll loop, not an event stream: you call
Poll and it returns the messages it has. The others deliver through events.
Quickstart, MQTT
uses
sgcWebSocket, sgcWebSocket_Protocols, sgcWebSocket_Classes, sgcWebSocket_Types;
procedure TForm1.FormCreate(Sender: TObject);
begin
FClient := TsgcWebSocketClient.Create(Self);
FClient.Host := 'test.mosquitto.org';
FClient.Port := 1883;
FClient.Specifications.RFC6455 := False; // raw TCP, not WebSocket
FMQTT := TsgcWSPClient_MQTT.Create(Self);
FMQTT.Client := FClient; // bind protocol to transport
FMQTT.MQTTVersion := mqtt311;
FMQTT.Authentication.Enabled := False;
FMQTT.OnMQTTConnect := MQTTConnect;
FMQTT.OnMQTTPublish := MQTTPublish;
FClient.Active := True;
end;
// fires once the broker has accepted CONNECT. Subscribe here, not earlier.
procedure TForm1.MQTTConnect(Connection: TsgcWSConnection; const Session: Boolean;
const ReasonCode: Integer; const ReasonName: string;
const ConnectProperties: TsgcWSMQTTCONNACKProperties);
begin
FMQTT.Subscribe('sensors/+/temperature', mtqsAtLeastOnce);
FMQTT.Publish('sensors/hello', 'online', mtqsAtLeastOnce, True);
end;
// every message on every subscribed topic arrives here
procedure TForm1.MQTTPublish(Connection: TsgcWSConnection; aTopic, aText: string;
PublishProperties: TsgcWSMQTTPUBLISHProperties);
begin
Memo1.Lines.Add(aTopic + ' = ' + aText);
end;
TmqttQoS is (mtqsAtMostOnce, mtqsAtLeastOnce, mtqsExactlyOnce, mtqsReserved).
The fourth value is the protocol's reserved slot, do not send it.
Quickstart, STOMP
STOMP names a subscription with an id you choose, and you use that id to unsubscribe and to acknowledge:
FSTOMP.Client := FClient;
FSTOMP.Subscribe('sub-1', '/queue/orders', ackIndividual);
FSTOMP.Send('/queue/orders', '{"id":42}', 'application/json');
TsgcSTOMPACK is (ackAuto, ackMultiple, ackIndividual). With ackAuto the
broker considers a message delivered the moment it sends it. With
ackIndividual it holds the message until you call ACK for that id, and
ackMultiple acknowledges everything up to that id at once. Transactions are
BeginTransaction, CommitTransaction and AbortTransaction, and every send
and acknowledgement takes the transaction name.
Last will, for MQTT
A last will is published by the broker on your behalf when your connection drops without a clean disconnect. Set it before connecting, never after:
FMQTT.LastWillTestament.Enabled := True;
FMQTT.LastWillTestament.Topic := 'clients/me/status';
FMQTT.LastWillTestament.Text := 'offline';
FMQTT.LastWillTestament.QoS := mtqsAtLeastOnce;
FMQTT.LastWillTestament.Retain := True;
Things that catch people out
- Subscribing before
OnMQTTConnectsilently does nothing. The socket being open is not the same as the broker having accepted CONNECT. - Two protocol components bound to the same client is the most common cause of
a broker rejecting the handshake. Set the unused ones to
nil. Specifications.RFC6455lives on the client, not the protocol, and its default is the WebSocket one. Brokers on port 1883 need it set toFalse.- QoS 2 involves a four-message exchange. If you are tracking delivery yourself
you need
OnMQTTPubRec,OnMQTTPubRelandOnMQTTPubComp, not justOnMQTTPubAck. - The reconnect and heartbeat settings belong to the transport client. Set
FClient.WatchDogandFClient.HeartBeat, and note MQTT also has its own protocol levelFMQTT.HeartBeatfor the MQTT keepalive, which is a different mechanism.
Routing
- Find a component:
reference/components-index.mdlists every component, itsunit, and its edition, grouped by Reg module. - Uses clause: add the component's
unit:value (shown on its API page) to yourusesclause. Nothing compiles without it. - API detail:
reference/api/<Component>.mdhas the Properties, Events and Methods, each in both Delphi and C++Builder form. - Option / enum / event types: property and event types link to
reference/types/<TypeName>.md, which documents the sub-properties of option classes, the values of enums, and the parameter list of event handlers. - Examples:
examples/index.mdis the full demo catalog;examples/<Component>.mdis a focused, real usage snippet for the most-used components. - Concepts:
concepts/overview.md(getting started + uses-clause rule) andconcepts/editions-and-features.md(which components your edition includes). - Bundled resources:
concepts/resources.mdlists the browser-side assets (JavaScript, HTML, CSS) the server components serve or embed, so a browser client works without an external CDN. - Version history:
reference/history.mdlists what changed in each sgcWebSockets release.
Editions
Components are gated by edition (Professional, Enterprise, All-Access) or by a feature define. Check the edition column in the components index, or concepts/editions-and-features.md, before relying on a component.
Only public and published members are documented. Method bodies, private fields and protected members are intentionally not included.