In an increasingly connected world, websites or IoT applications must be updated in real-time.
A way to deliver information instantly to your sites is to use the Websocket protocol that provides a full-duplex communication channel between a server and a client. From the v20, 4D provides commands to create a Websocket server.
Commands to Create a Websocket Server
To manage your websocket server, 4D provides 2 new classes:
- The first manages the server itself, 4D.WebSocketServer
- The second manages the websocket connections: 4D.WebSocketConnection
To demonstrate this feature, let’s create a simple chat server!
Before using the websocket server class, your 4D webserver must be started!
4D.WebSocketServer
This class allows you to manage different events that occur on your server. To do so, you need to create a class with the below functions:
- onConnection(), called when a new connection is requested.
- onOpen(), called when the server starts
- onTerminate(), called when the server stops
- onError(), called when an error occurred.
In our example, we need first to manage the connection request. With the onConnection() function, you can cancel a connection by returning Null or an object that will be used to manage the message sent or received. In the example below, we return the WSConnectionHandler class (described in the next section):
Function onConnection($wss : Object; $param : Object) : Object
// call the VerifyAddress method to verify if the remote address is allow to connect
If (VerifyAddress($param.request.remoteAddress))
// The connection is allowed
// The WSConnectionHandler object returned is used
// by 4D to instantiate the 4D.WebSocketConnection object
// related to this connection
return cs.WSConnectionHandler.new()
Else
// The connection is canceled
return Null
End if
Now, we want to log the start, close, and errors, so we create a WSServerHandler class:
Class constructor
Function onOpen($wss : Object; $param : Object)
LogFile("*** Server started")
Function onTerminate($wss : Object; $param : Object)
LogFile("*** Server closed")
Function onError($wss : Object; $param : Object)
LogFile("!!! Server error: "+$param.statusText)
4D.WebSocketConnection
This class allows you to manage different events during a given connection. To do so, you need to create a class with the below functions:
- onMessage(), called each time a message arrives through this connection.
- onOpen(), called when the 4D.WebSocketConnection object is created
- onTerminate(), called when the 4D.WebSocketConnection object is terminated
- onError(), called when an error occurred
To do our chat, this class will be the WSConnectionHandler class. It:
- warns other users that a new user is connected when the connection is opened
- warns other users that a user is disconnected when the connection is terminated
- broadcast the received messages to all the other chat clients connected when a message is received.
Function onMessage($ws : 4D.WebSocketConnection; $message : Object)
// resend the message to all the chat clients
This.broadcast($ws;$message.data)
Function onOpen($ws : 4D.WebSocketConnection; $message : Object)
// Send a message to the new connected user
$ws.send("Welcome on the chat!")
// Send message "New client connected" to all the other chat clients
This.broadcast($ws;"New client connected")
Function onTerminate($ws : 4D.WebSocketConnection; $message : Object)
// Send message "Client disconnected" to all the other chat clients
This.broadcast($ws;"Client disconnected")
Function broadcast($ws : 4D.WebSocketConnection; $message : Text)
var $client:4D.WebSocketConnection
// resend the message to all the chat clients
For each ($client; $ws.wss.connections)
// Verify that the id is not the current connection
If ($client.id#$ws.id)
$client.send($message)
End if
End for each
All left is to start the websocket server using the classes created above. A websocket server must be started in a worker, so we create a new process with the CALL WORKER command and instantiate the 4D.WebSocketServer in it:
var $handler:cs.WSSHandler
$handler:=cs.WSServerHandler.new()
CALL WORKER("WebSocketServer"; Formula(WSS:=4D.WebSocketServer.new($handler)))
//Assign a variable (WSS) to the WebSocket allows you to call WSS.terminate() afterwards
The websocket server created will exist until the worker is killed or the .terminate() function is called.
CALL WORKER("WebSocketServer"; Formula(WSS.terminate()))
Client-side
You can find below an example of code in HTML and Javascript to create a chat interface:
This code is designed to work with a local webserver at HTTP port 80 (line 18: const urlwss=”ws://127.0.0.1:80/”;).
Check out this feature with the HDI above and the documentation for more details!