WAMP Protocol
Routed RPC and publish-subscribe over WebSocket for Delphi, C++ Builder and .NET. WAMP v1 client and server, JSON payloads carried over the wamp WebSocket subprotocol.
Routed RPC and publish-subscribe over WebSocket for Delphi, C++ Builder and .NET. WAMP v1 client and server, JSON payloads carried over the wamp WebSocket subprotocol.
WAMP is an open WebSocket subprotocol that provides two asynchronous messaging patterns: RPC and PubSub.
TsgcWSPClient_WAMP| Standards & specs | WAMP specification (latest IETF draft) · WAMP specifications index |
| Component class | TsgcWSPClient_WAMP (unit sgcWebSocket_Protocols, ancestor TsgcWSProtocol_WAMP_Client in unit sgcWebSocket_Protocol_WAMP_Client) |
| Frameworks | VCL, FireMonkey, Lazarus / FPC, .NET; TsgcWSPServer_WAMP is Delphi and C++ Builder only |
| Platforms | Windows, macOS, Linux, iOS, Android |
The principal published / public properties used to configure and drive the component. Consult the online help for the full list.
Client | References the TsgcWebSocketClient that carries WAMP v1 frames over a WebSocket connection. |
Broker | References a raw-TCP broker component so the WAMP subprotocol travels over a plain socket instead of a WebSocket. |
Version | Read-only string with the sgcWebSockets build version of the WAMP subprotocol component. |
The principal public methods exposed by the component.
CancelCall() | Requests cancellation of an in-flight RPC previously started with Call. |
Subscribe() | Registers interest in a PubSub topic so that matching events are delivered to the OnEvent handler. |
UnSubscribe() | Cancels a prior subscription so that further events on the topic no longer reach this client. |
Publish() | Broadcasts an event payload to every subscriber of the given topic, with optional exclude/eligible session lists. |
Call() | Invokes a remote procedure identified by its URI and correlates the eventual result or error to the supplied call id. |
WriteData() | Sends a pre-built text or binary WAMP frame directly over the underlying WebSocket transport. |
Prefix() | Registers a short label that expands to a full URI, letting later Call, Subscribe and Publish frames use a compact notation. |
The component exposes the following published events; consult the online help for full event-handler signatures.
OnBinary | Fires when the server sends a binary WebSocket frame that is not part of the standard WAMP v1 text protocol. |
OnCallError | Fires when a remote procedure invoked by Call fails on the server or is rejected. |
OnCallProgressResult | Fires for each interim chunk of a streaming RPC before the final result arrives via OnCallResult. |
OnCallResult | Fires once per successful RPC to deliver the final result of a Call invocation. |
OnConnect | Fires when the underlying WebSocket (or raw TCP) transport has successfully connected to the server. |
OnDisconnect | Fires when the underlying transport closes, ending the current WAMP session. |
OnError | Fires when the component detects a transport or protocol-level error condition. |
OnEvent | Fires when a published event arrives on a topic this client has previously subscribed to. |
OnException | Fires when a Delphi exception is raised inside one of the component's worker threads or event handlers. |
OnFragmented | Fires for each fragment of a multi-frame WebSocket message before reassembly. |
OnMessage | Fires for incoming text frames that the WAMP decoder did not route to a higher-level RPC or PubSub handler. |
OnRawMessage | Fires before WAMP decoding, giving the application first look at every incoming text frame with an option to suppress further processing. |
OnWelcome | Fires when the server's WELCOME frame has been received, signalling that the WAMP session is fully open and ready for RPC and PubSub calls. |
Drop the component on a form, configure the properties below and activate it. The snippet that follows shows the typical WAMP client connect configuration.
oClient := TsgcWebSocketClient.Create(nil); oClient.Host := '127.0.0.1'; oClient.Port := 80; oClientWAMP := TsgcWSPClient_WAMP.Create(nil); oClientWAMP.Client := oClient; oClientWAMP.OnWelcome := OnWelcomeEvent; oClientWAMP.OnEvent := OnEventEvent; oClient.Active := True; procedure TForm1.OnWelcomeEvent(Connection: TsgcWSConnection; SessionId, ProtocolVersion, ServerIdent: string); begin // CURIE prefix, then subscribe using the short form oClientWAMP.Prefix('app', 'http://example.com/topics#'); oClientWAMP.Subscribe('app:myTopic'); end;
oClient = new TsgcWebSocketClient(this); oClient->Host = "127.0.0.1"; oClient->Port = 80; oClientWAMP = new TsgcWSPClient_WAMP(this); oClientWAMP->Client = oClient; oClientWAMP->OnWelcome = OnWelcomeEvent; oClientWAMP->OnEvent = OnEventEvent; oClient->Active = true; void __fastcall TForm1::OnWelcomeEvent(TsgcWSConnection *Connection, String SessionId, String ProtocolVersion, String ServerIdent) { oClientWAMP->Prefix("app", "http://example.com/topics#"); oClientWAMP->Subscribe("app:myTopic"); }
oClient = new TsgcWebSocketClient(); oClient.Host = "127.0.0.1"; oClient.Port = 80; oClientWAMP = new TsgcWSPClient_WAMP(); oClientWAMP.Client = oClient; oClientWAMP.OnWelcome += OnWelcomeEvent; oClientWAMP.OnEvent += OnEventEvent; oClient.Active = true; void OnWelcomeEvent(TsgcWSConnection Connection, string SessionId, string ProtocolVersion, string ServerIdent) { oClientWAMP.Prefix("app", "http://example.com/topics#"); oClientWAMP.Subscribe("app:myTopic"); }
Each scenario shows the configuration and method calls needed to drive the component through a specific real-world flow. Every identifier below is taken from the component declaration shipped with the library.
A subscriber provides the topics it is interested in and then receives every event published to them, delivered through OnEvent. A publisher just calls Publish with the topic and the payload, there is no need to subscribe to a topic in order to publish on it. Publish also accepts an exclude and an eligible list so the router can filter recipients.
procedure TForm1.OnEventEvent(Connection: TsgcWSConnection; TopicURI, Event: string); begin DoLog(TopicURI + ': ' + Event); end; oClientWAMP.Subscribe('myTopic'); oClientWAMP.Publish('myTopic', 'Hello subscribers myTopic'); oClientWAMP.UnSubscribe('myTopic');
void __fastcall TForm1::OnEventEvent(TsgcWSConnection *Connection, String TopicURI, String Event) { DoLog(TopicURI + ": " + Event); } oClientWAMP->Subscribe("myTopic"); oClientWAMP->Publish("myTopic", "Hello subscribers myTopic"); oClientWAMP->UnSubscribe("myTopic");
void OnEventEvent(TsgcWSConnection Connection, string TopicURI, string Event) { DoLog(TopicURI + ": " + Event); } oClientWAMP.Subscribe("myTopic"); oClientWAMP.Publish("myTopic", "Hello subscribers myTopic"); oClientWAMP.UnSubscribe("myTopic");
Call takes a call id you generate, the procedure URI and an optional argument string. The router answers with a result, delivered through OnCallResult, or with an error, delivered through OnCallError. CancelCall aborts a call that is still in flight. Partial answers arrive through OnCallProgressResult, an sgcWebSockets extension to WAMP v1.
oClientWAMP.OnCallResult := OnCallResultEvent; oClientWAMP.OnCallError := OnCallErrorEvent; oClientWAMP.Call('call-1', 'GetTime'); oClientWAMP.Call('call-2', 'GetProgressiveTime', '20'); procedure TForm1.OnCallResultEvent(Connection: TsgcWSConnection; CallId, Result: string); begin DoLog(CallId + ' = ' + Result); end; procedure TForm1.OnCallErrorEvent(Connection: TsgcWSConnection; CallId, ErrorURI, ErrorDesc, ErrorDetails: string); begin DoLog(CallId + ' failed: ' + ErrorDesc); end;
oClientWAMP->OnCallResult = OnCallResultEvent; oClientWAMP->OnCallError = OnCallErrorEvent; oClientWAMP->Call("call-1", "GetTime"); oClientWAMP->Call("call-2", "GetProgressiveTime", "20"); void __fastcall TForm1::OnCallResultEvent(TsgcWSConnection *Connection, String CallId, String Result) { DoLog(CallId + " = " + Result); } void __fastcall TForm1::OnCallErrorEvent(TsgcWSConnection *Connection, String CallId, String ErrorURI, String ErrorDesc, String ErrorDetails) { DoLog(CallId + " failed: " + ErrorDesc); }
oClientWAMP.OnCallResult += OnCallResultEvent; oClientWAMP.OnCallError += OnCallErrorEvent; oClientWAMP.Call("call-1", "GetTime"); oClientWAMP.Call("call-2", "GetProgressiveTime", "20"); void OnCallResultEvent(TsgcWSConnection Connection, string CallId, string Result) { DoLog(CallId + " = " + Result); } void OnCallErrorEvent(TsgcWSConnection Connection, string CallId, string ErrorURI, string ErrorDesc, string ErrorDetails) { DoLog(CallId + " failed: " + ErrorDesc); }
TsgcWSPServer_WAMP turns a TsgcWebSocketServer into a WAMP v1 router. Handle OnCall, then answer with CallResult for a single result, CallProgressResult for partial results, or CallError with a call id, an error URI and an error description. Use Event to push a value to every subscriber of a topic. The server-side component ships in the Delphi and C++ Builder libraries, the .NET library provides the WAMP client only.
oServer := TsgcWebSocketServer.Create(nil); oServer.Port := 80; oServerWAMP := TsgcWSPServer_WAMP.Create(nil); oServerWAMP.Server := oServer; oServerWAMP.OnCall := OnServerCallEvent; oServer.Active := True; procedure TForm1.OnServerCallEvent(Connection: TsgcWSConnection; const CallId, ProcUri, Arguments: string); var i, vNum: Integer; begin if ProcUri = 'GetTime' then oServerWAMP.CallResult(CallId, FormatDateTime('yyyymmdd hh:nn:ss', Now)) else if ProcUri = 'GetProgressiveTime' then begin vNum := StrToInt(Arguments); for i := 1 to vNum do begin if i = vNum then oServerWAMP.CallResult(CallId, FormatDateTime('yyyymmdd hh:nn:ss', Now)) else oServerWAMP.CallProgressResult(CallId, FormatDateTime('yyyymmdd hh:nn:ss', Now)); end; end else oServerWAMP.CallError(CallId, 'wamp:error#notfound', 'Unknown method'); end;
oServer = new TsgcWebSocketServer(this); oServer->Port = 80; oServerWAMP = new TsgcWSPServer_WAMP(this); oServerWAMP->Server = oServer; oServerWAMP->OnCall = OnServerCallEvent; oServer->Active = true; void __fastcall TForm1::OnServerCallEvent(TsgcWSConnection *Connection, const String CallId, const String ProcUri, const String Arguments) { if (ProcUri == "GetTime") { oServerWAMP->CallResult(CallId, FormatDateTime("yyyymmdd hh:nn:ss", Now())); } else if (ProcUri == "GetProgressiveTime") { int vNum = StrToInt(Arguments); for (int i = 1; i <= vNum; i++) { if (i == vNum) oServerWAMP->CallResult(CallId, FormatDateTime("yyyymmdd hh:nn:ss", Now())); else oServerWAMP->CallProgressResult(CallId, FormatDateTime("yyyymmdd hh:nn:ss", Now())); } } else { oServerWAMP->CallError(CallId, "wamp:error#notfound", "Unknown method"); } }
// TsgcWSPServer_WAMP is not part of the .NET library. Point the .NET // WAMP client at a Delphi or C++ Builder router, or at any other // WAMP v1 router, and consume the results through OnCallResult. oClientWAMP.OnCallResult += OnCallResultEvent; oClientWAMP.Call("call-1", "GetTime");
Every external claim links back to a primary source. The online-help references decode the canonical deep-link the company maintains for this component.
Demos\02.WebSocket_Protocols\04.WAMP_Protocol
.net\demos\02.WebSocket_Protocols\04.WAMP_Protocol