Nuovo server Websocket integrato

Tradotto automaticamente da Deepl

In un mondo sempre più connesso, i siti web o le applicazioni IoT devono essere aggiornati in tempo reale.

Un modo per fornire informazioni istantaneamente ai siti è utilizzare il protocollo Websocket, che fornisce un canale di comunicazione full-duplex tra un server e un client. Dalla v20, 4D fornisce i comandi per creare un server Websocket.

Comandi per creare un server Websocket

Per gestire il server Websocket, 4D fornisce due nuove classi:

  • La prima gestisce il server stesso, 4D.WebSocketServer
  • La seconda gestisce le connessioni websocket: 4D.WebSocketConnection

 

Per dimostrare questa funzione, creiamo un semplice server di chat!

Prima di utilizzare la classe websocket server, il server web 4D deve essere avviato!

4D.WebSocketServer

Questa classe consente di gestire i diversi eventi che si verificano sul server. Per farlo, è necessario creare una classe con le seguenti funzioni:

  • onConnection(), chiamata quando viene richiesta una nuova connessione.
  • onOpen(), chiamata quando il server si avvia
  • onTerminate(), chiamata quando il server si ferma
  • onError(), chiamata quando si verifica un errore.

Nel nostro esempio, dobbiamo innanzitutto gestire la richiesta di connessione. Con la funzione onConnection(), è possibile annullare una connessione restituendo Null o un oggetto che verrà utilizzato per gestire il messaggio inviato o ricevuto. Nell’esempio che segue, restituiamo la classe WSConnectionHandler (descritta nella prossima sezione):

Function onConnection($wss : Object; $param : Object) : Object
 // Richiamiamo il metodo VerifyAddress per verificare se l'indirizzo remoto è autorizzato a connettersi
If (VerifyAddress($param.request.remoteAddress))
// La connessione è consentita
// L'oggetto WSConnectionHandler restituito viene utilizzato 
// da 4D per istanziare l'oggetto 4D.WebSocketConnection
// relativo a questa connessione
return cs.WSConnectionHandler.new() 
Else 
// La connessione viene annullata
return Null 
End if 

Ora vogliamo registrare l’avvio, la chiusura e gli errori, quindi creiamo una classe WSServerHandler:

Costruttore della 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

Questa classe consente di gestire diversi eventi durante una determinata connessione. Per farlo, è necessario creare una classe con le funzioni seguenti:

  • onMessage(), chiamata ogni volta che arriva un messaggio attraverso questa connessione.
  • onOpen(), chiamata quando viene creato l’oggetto 4D.WebSocketConnection
  • onTerminate(), chiamata quando l’oggetto 4D.WebSocketConnection viene terminato
  • onError(), chiamata quando si verifica un errore

 

Per la nostra chat, questa classe sarà la classe WSConnectionHandler. Essa:

  • avvisa gli altri utenti che un nuovo utente si è connesso quando viene aperta la connessione
  • avvisa gli altri utenti che un utente si è disconnesso quando la connessione viene terminata
  • trasmette i messaggi ricevuti a tutti gli altri client di chat connessi quando viene ricevuto un messaggio.

 

Function onMessage($ws : 4D.WebSocketConnection; $messaggio : Object)
// reinvio del messaggio a tutti i client di chat
This.broadcast($ws;$messaggio.dati)

Function onOpen($ws : 4D.WebSocketConnection; $messaggio : Object)
// Invia un messaggio al nuovo utente connesso 
$ws.send("Welcome on the chat!")
// Invia il messaggio "New client connected" a tutti gli altri client di chat
This.broadcast($ws; "New client connected")

Function onTerminate($ws : 4D.WebSocketConnection; $message : Object)
// Invia il messaggio "Client disconnesso" a tutti gli altri client di chat
This.broadcast($ws; "Client disconnesso")

Function broadcast($ws : 4D.WebSocketConnection; $message : Text)
var $client:4D.WebSocketConnection
// reinvia il messaggio a tutti i client della chat
For each ($client; $ws.wss.connections)
// Verifica che l'id non sia la connessione corrente
If ($client.id#$ws.id)
$client.send($messaggio)
End if 
End for each 

Non resta che avviare il server websocket utilizzando le classi create in precedenza. Un server websocket deve essere avviato in un worker, quindi creiamo un nuovo processo con il comando CALL WORKER e vi istanziamo il 4D.WebSocketServer:

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

CALL WORKER("WebSocketServer"; Formula(WSS:=4D.WebSocketServer.new($handler))
//Assegnare una variabile (WSS) al WebSocket permette di chiamare WSS.terminate() in seguito

Il server websocket creato esisterà fino a quando il worker non verrà ucciso o verrà richiamata la funzione .terminate().

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

Lato client

Di seguito è riportato un esempio di codice in HTML e Javascript per creare un’interfaccia di chat:

Questo codice è progettato per funzionare con un server web locale sulla porta HTTP 80 (riga 18: const urlwss=”ws://127.0.0.1:80/”;).

Per maggiori dettagli, date un’occhiata a questa funzione con l’HDI qui sopra e alla documentazione!

Fabrice Mainguené
- Product Owner -Fabrice Mainguené si è unito al team di 4D Program nel novembre 2016. In qualità di Product Owner, è incaricato di scrivere le storie degli utenti e di tradurle in specifiche funzionali. Il suo ruolo è anche quello di assicurarsi che l'implementazione della funzionalità fornita soddisfi le esigenze del cliente.Dopo aver conseguito una laurea in Informatica presso il CNAM, Fabrice è entrato a far parte di una piccola società di pubblicazione di software come sviluppatore Windev. In seguito ha lavorato per diverse aziende del settore industriale e commerciale come sviluppatore Windev e web e come consulente tecnico su nuove funzionalità.