TTMSFNCWebSocketServer
The TTMSFNCWebSocketServer
is a non-visual component enabling communication to websocket clients. It implements the RFC 6455 standard for websocket communication protocol.
Start/stop the server
Starting/stopping the server is as simple as setting the Active
property.
procedure TForm1.startBtnClick(Sender: TObject);
begin
TMSFNCWebSocketServer1.Active := True;
end;
procedure TForm1.stopBtnClick(Sender: TObject);
begin
TMSFNCWebSocketServer1.Active := False;
end;
Allowing connections
By default all connections are allowed as long as they initiate a valid handshake request. After the handshake request is validated, the OnAllow
event is triggered. This event has an AAllow: Boolean
parameter which can be used to allow or disallow a connection regardless of the handshake request. The AConnection
parameter gives access to the HandshakeRequest
property which lets the details of the request be inspected.
procedure TForm2.TMSFNCWebSocketServer1Allow(Sender: TObject;
AConnection: TTMSFNCWebSocketServerConnection; var aAllow: Boolean);
begin
//Allow all connections
AAllow := True
end;
Send data
Use BroadcastMessage(AMessage: string)
or BroadcastData(AData: TBytes)
to broadcast a string or binary messages to all connected clients.
procedure TForm1.broadcastBtnClick(Sender: TObject);
begin
TMSFNCWebSocketServer1.BroadcastMessage('Hello client!');
end;
Use SendMessageTo(AMessage, ASelector)
or SendDataTo(AData, ASelector)
to send string or binary messages to connected clients. The ASelector
callback determines which clients should the message be sent to.
//Forward incoming message to all client, except the one the message came from
procedure TForm2.TMSFNCWebSocketServer1MessageReceived(Sender: TObject;
AConnection: TTMSFNCWebSocketConnection; const aMessage: string);
begin
TMSFNCWebSocketServer1.SendMessageTo(AMessage, function(AClientConnection: TTMSFNCWebSocketServerConnection): Boolean
begin
Result := AClientConnection <> AConnection;
end);
end;
Send in multiple frames
By default all messages are sent in one single frame. If SplitMessage
is set to True
, the message will be split up into multiple frames based on size defined by FrameSize
. Size of the frame includes frame headers too.
Receive data/messages
When a string message arrives from one of the clients the OnMessageReceived
event will be triggered. The AMessage
parameter will contain the string message from the client.
When a binary message arrives from one of the clients the OnBinaryDataReceived
event will be triggered. The AData
parameter will contain the binary message from the client.
Ping and pong
Whenever a ping message arrives from a client the OnPing
event is triggered and an automatic pong message is sent back.
If the Options
property contains the twsoManualPong
value the poing message is NOT sent automatically. In this case the OnPing
can be used to send manually or skip it entirely.
procedure TForm2.TMSFNCWebSocketServer1Ping(Sender: TObject;
AConnection: TTMSFNCWebSocketConnection; const aData: TArray<System.Byte>);
begin
AConnection.SendSimpleFrame(focPong);
end;
The OnPong
event is triggered whenever a pong message is received from a client.
Custom connection data
The TTMSFNCWebSocketServerConnection.UserData
object property allows you to store any kind of custom data paired to your connection. It also has an OwnsUserData
property which will free the object automatically if it's set to True
. If it's set to False
, the object needs to be released manually.
When to create/assign the UserData
object is depending on the use-case. When the data that needs storing is arriving from the client itself as a form of message, then the OnMessageReceived
event is the place to handle this. For example as a form of JSON message:
type
TMyDataObject = class(TObject)
private
FID: string;
public
property ID: string read FID write FID;
end;
procedure TForm1.TMSFNCWebSocketServer1MessageReceived(Sender: TObject;
AConnection: TTMSFNCWebSocketConnection; const aMessage: string);
var
json: TJSONValue;
jObj: TJSONObject;
t, id, s, lID: string;
i: Integer;
begin
json := TJSONObject.ParseJSONValue(AMessage);
try
if json.TryGetValue<string>('type', t) then
begin
if (t = 'user-data') and not Assigned(TTMSFNCWebSocketServerConnection(AConnection).UserData) then
begin
json.TryGetValue<string>('id', id);
TTMSFNCWebSocketServerConnection(AConnection).OwnsUserData := True;
TTMSFNCWebSocketServerConnection(AConnection).UserData := TMyDataObject.Create;
TMyDataObject(TTMSFNCWebSocketServerConnection(AConnection).UserData).ID := id;
//...
end
else if t = 'join' then
begin
//...
end
//elseā¦.
finally
json.Free;
end;
end;
When the server is the one that automatically assigns some data, it needs to be inspected where that should happen.
For example:
The server wants to assign a unique ID for each new connection. In this case we can use the OnHandshakeResponseSent
event where the server responds to the websocket handshake so the connection is estabilished.
procedure TForm1.TMSFNCWebSocketServer1HandshakeResponseSent(Sender: TObject;
AConnection: TTMSFNCWebSocketServerConnection);
begin
AConnection.OwnsUserData := True;
AConnection.UserData := TMyDataObject.Create;
TMyDataObject(AConnection.UserData).ID := GetMyUniqueID;
end;
Secure connection
Traffic over a websocket server can be protected via TLS. In order to enable this, set the UseSSL
property to True
.
The CertificateFile
, CertificateKeyFile
and RootCertificateFile
properties can be used to define the path to the certificate file(s).
For secure connection OpenSSL libraries are required.
Properties
Property name | Description |
---|---|
Active: Boolean | Start or stop the server. |
CertificateFile: string | Path to the certificate file. Used when UseSSL is set to True . |
CertificateKeyFile: string | Path to the certificate key file. Used when UseSSL is set to True . |
FrameSize: UIn64 | The size of each frame to be sent. Used when SplitMessage is set to True . |
Options: TTMSFNCWebsocketOptions | A set connection related options. Values are: - twsoFrameByFrame : Do not assemble the frames - twsoSkipUpgradeCheck : Do not check handshake Upgrade header - twsoSkipVersionCheck : Do not check handshake version - twsoManualPong : Do not send pong automatucally - twsoManualClose : Do not send close reply automatically |
PathName: string | Name of the path. For example: ws://localhost:8888/path |
Port: Integer | Port number. Default setting is 8888 . |
RootCertificateFile: string | Path to the root certificate file. Used when UseSSL is set to True . |
SplitMessage: Boolean | If set to True , messages are split into multiple frames based on FrameSize . |
UseSSL: Boolean | If set to True , the server communication is protected via TLS. |
Methods
Method name | Description |
---|---|
BroadcastMessage(AMessage: string) | Broadcasts a string message to all connected clients. |
BroadcastData(AData: TBytes) | Broadcasts a binary message to all connected clients. |
SendMessageTo(AMessage: string; ASelector: TTMSFNCWebSocketSendToCallback) | Sends a string message to connected clients. The ASelector callback determines to which clients the message should be sent. |
SendDataTo(AData: TBytes; ASelector: TTMSFNCWebSocketSendToCallback) | Sends a binary message to connected clients. The ASelector callback determines to which clients the message should be sent. |
Events
Event name | Description |
---|---|
OnAllow | Event triggered to allow or disallow a client connection. |
OnBinaryDataReceived | Event triggered when a binary message arrives to the server. |
OnClose | Event triggered when a close frame is sent by the client. |
OnConnect | Event triggered when a clients connects to the server. This is not equal to when the client is connected (handshake successfully finished). |
OnDisconnect | Event triggered when a client disconnects. |
OnHandshakeResponseSent | Event triggered when the handshake response is sent to the client. |
OnMessageReceived | Event triggered when a string message arrives to the server. |
OnPing | Event triggered when a ping message arrives from a client. |
OnPong | Event triggered when a pong message arrives from a client. |