Nouveau serveur Websocket intégré

Traduit automatiquement de Deepl

Dans un monde de plus en plus connecté, les sites web ou les applications IoT doivent être mis à jour en temps réel.

Un moyen de fournir des informations instantanément à vos sites est d’utiliser le protocole Websocket qui fournit un canal de communication full-duplex entre un serveur et un client. À partir de la v20, 4D fournit des commandes pour créer un serveur Websocket.

Commandes pour créer un serveur Websocket

Pour gérer votre serveur Websocket, 4D fournit deux nouvelles classes :

  • La première gère le serveur lui-même, 4D.WebSocketServer
  • La seconde gère les connexions websocket : 4D.WebSocketConnection

 

Pour démontrer cette fonctionnalité, créons un simple serveur de chat !

Avant d’utiliser la classe serveur websocket, votre serveur 4D doit être démarré !

4D.WebSocketServer

Cette classe vous permet de gérer les différents événements qui se produisent sur votre serveur. Pour ce faire, vous devez créer une classe avec les fonctions suivantes :

  • onConnection(), appelée lorsqu’une nouvelle connexion est demandée.
  • onOpen(), appelée lorsque le serveur démarre
  • onTerminate(), appelée lorsque le serveur s’arrête
  • onError(), appelée lorsqu’une erreur se produit.

Dans notre exemple, nous devons d’abord gérer la demande de connexion. La fonction onConnection() permet d’annuler une connexion en renvoyant Null ou un objet qui sera utilisé pour gérer le message envoyé ou reçu. Dans l’exemple ci-dessous, nous renvoyons la classe WSConnectionHandler (décrite dans la section suivante) :

Fonction onConnection($wss : Object ; $param : Object) : Objet
 // appeler la méthode VerifyAddress pour vérifier si l'adresse distante est autorisée à se connecter
If (VerifyAddress($param.request.remoteAddress))
// La connexion est autorisée
// L'objet WSConnectionHandler renvoyé est utilisé 
// par 4D pour instancier l'objet 4D.WebSocketConnection
// lié à cette connexion
return cs.WSConnectionHandler.new() 
Else 
// La connexion est annulée
return Null 
End if 

Maintenant, nous voulons enregistrer le démarrage, la fermeture et les erreurs, donc nous créons une classe WSServerHandler :

Constructeur de la classe

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

Cette classe permet de gérer différents événements lors d’une connexion donnée. Pour cela, il faut créer une classe avec les fonctions ci-dessous :

  • onMessage(), appelée à chaque fois qu’un message arrive par cette connexion.
  • onOpen(), appelée lors de la création de l’objet 4D.WebSocketConnection
  • onTerminate(), appelée lorsque l’objet 4D.WebSocketConnection est terminé
  • onError(), appelée lorsqu’une erreur s’est produite

 

Pour réaliser notre chat, cette classe sera la classe WSConnectionHandler. Elle :

  • avertit les autres utilisateurs qu’un nouvel utilisateur est connecté lorsque la connexion est ouverte
  • avertit les autres utilisateurs qu’un utilisateur est déconnecté lorsque la connexion est terminée
  • diffuse les messages reçus à tous les autres clients de chat connectés lorsqu’un message est reçu.

 

Function onMessage($ws : 4D.WebSocketConnection ; $message : Object)
// renvoyer le message à tous les clients de chat
This.broadcast($ws;$message.data)

Function onOpen($ws : 4D.WebSocketConnection ; $message : Object)
// envoie un message au nouvel utilisateur connecté 
$ws.send("Welcome on the chat !")
// envoie le message "New client connected" à tous les autres clients du chat
This.broadcast($ws ; "New client connected")

Function onTerminate($ws : 4D.WebSocketConnection ; $message : Object)
// Envoi du message "Client déconnecté" à tous les autres clients de chat
This.broadcast($ws ; "Client déconnecté")

Function broadcast($ws : 4D.WebSocketConnection ; $message : Text)
var $client:4D.WebSocketConnection
// renvoyer le message à tous les clients de chat
For each ($client ; $ws.wss.connections)
// Vérifier que l'id n'est pas la connexion actuelle
If ($client.id#$ws.id)
$client.send($message)
End if 
End for each 

Il ne reste plus qu’à démarrer le serveur websocket en utilisant les classes créées ci-dessus. Un serveur websocket doit être démarré dans un worker, nous créons donc un nouveau processus avec la commande CALL WORKER et nous y instancions le 4D.WebSocketServer :

var $handler:cs.WSSHandler
$handler:=cs.WSServerHandler.new()

CALL WORKER("WebSocketServer" ; Formula(WSS:=4D.WebSocketServer.new($handler)))
//Assigner une variable (WSS) à la WebSocket permet d'appeler WSS.terminate() par la suite.

The websocket server created will exist until the worker is killed or the .terminate() function is called.

CALL WORKER("WebSocketServer"; Formula(WSS.terminate()))

Côté client

Vous trouverez ci-dessous un exemple de code en HTML et Javascript pour créer une interface de chat :

Ce code est conçu pour fonctionner avec un serveur web local sur le port HTTP 80 (ligne 18 : const urlwss= »ws://127.0.0.1:80/ » ;).

Découvrez cette fonctionnalité avec le HDI ci-dessus et la documentation pour plus de détails !

Fabrice Mainguené
- Product Owner -Fabrice Mainguené a rejoint l'équipe du programme 4D en novembre 2016. En tant que Product Owner, il est en charge de rédiger les user stories puis de les traduire en spécifications fonctionnelles. Son rôle est également de s'assurer que l'implémentation de la fonctionnalité livrée répond au besoin du client.Après avoir obtenu une licence en informatique au CNAM, Fabrice a rejoint une petite société d'édition de logiciels en tant que développeur Windev. Il a ensuite travaillé pour différentes entreprises dans les domaines de l'industrie et du commerce en tant que développeur Windev et web ainsi que conseiller technique sur les nouvelles fonctionnalités.