Neuer integrierter Websocket-Server

In einer zunehmend vernetzten Welt müssen Websites oder IoT-Anwendungen in Echtzeit aktualisiert werden.

Eine Möglichkeit, Informationen sofort an Ihre Websites zu liefern, ist die Verwendung des Websocket-Protokolls, das einen Vollduplex-Kommunikationskanal zwischen einem Server und einem Client bietet. Ab v20 bietet 4D Befehle zur Erstellung eines Websocket Servers.

Befehle zum Erstellen eines Websocket-Servers

Um Ihren Websocket Server zu verwalten, bietet 4D 2 neue Klassen:

  • Die erste verwaltet den Server selbst, 4D.WebSocketServer
  • Die zweite Klasse verwaltet die Websocket-Verbindungen: 4D.WebSocketConnection

 

Um diese Funktion zu demonstrieren, lassen Sie uns einen einfachen Chat-Server erstellen!

Bevor Sie die Websocket Server Klasse verwenden, muss Ihr 4D Webserver gestartet sein!

4D.WebSocketServer

Mit dieser Klasse können Sie verschiedene Ereignisse, die auf Ihrem Server auftreten, verwalten. Dazu müssen Sie eine Klasse mit den folgenden Funktionen erstellen:

  • onConnection(), wird aufgerufen, wenn eine neue Verbindung angefordert wird.
  • onOpen(), wird aufgerufen, wenn der Server startet.
  • onTerminate(), wird aufgerufen, wenn der Server stoppt.
  • onError(), die aufgerufen wird, wenn ein Fehler auftritt.

In unserem Beispiel müssen wir zunächst die Verbindungsanforderung verwalten. Mit der Funktion onConnection() können Sie eine Verbindung abbrechen, indem Sie Null oder ein Objekt zurückgeben, das zur Verwaltung der gesendeten oder empfangenen Nachricht verwendet wird. Im folgenden Beispiel geben wir die Klasse WSConnectionHandler zurück (die im nächsten Abschnitt beschrieben wird):

Function onConnection($wss : Object; $param : Object) : Object
 // Aufruf der Methode VerifyAddress, um zu prüfen, ob die Remote-Adresse für die Verbindung zulässig ist
If (VerifyAddress($param.request.remoteAddress))
// Die Verbindung ist zulässig
// Das zurückgegebene WSConnectionHandler Objekt wird 
// von 4D verwendet, um das 4D.WebSocketConnection-Objekts
// zu dieser Verbindung
return cs.WSConnectionHandler.new() 
Else 
// Die Verbindung wird abgebrochen
return Null 
End if 

Nun wollen wir den Start, das Schließen und die Fehler protokollieren, also erstellen wir eine WSServerHandler-Klasse:

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

Diese Klasse ermöglicht es Ihnen, verschiedene Ereignisse während einer bestimmten Verbindung zu verwalten. Dazu müssen Sie eine Klasse mit den folgenden Funktionen erstellen:

  • onMessage(), die jedes Mal aufgerufen wird, wenn eine Nachricht über diese Verbindung ankommt.
  • onOpen(), wird aufgerufen, wenn das Objekt 4D.WebSocketConnection erstellt wird.
  • onTerminate(), wird aufgerufen, wenn das Objekt 4D.WebSocketConnection beendet wird.
  • onError(), wird aufgerufen, wenn ein Fehler auftritt.

 

Für unseren Chat wird diese Klasse die WSConnectionHandler-Klasse sein. Sie:

  • Warnt andere Benutzer, dass ein neuer Benutzer verbunden ist, wenn die Verbindung geöffnet wird.
  • Warnt andere Benutzer, dass ein Benutzer getrennt wird, wenn die Verbindung beendet wird.
  • Sendet die empfangenen Nachrichten an alle anderen angeschlossenen Chat-Clients, wenn eine Nachricht empfangen wird.

 

Function onMessage($ws : 4D.WebSocketConnection; $message : Object)
// sendet die Nachricht erneut an alle Chat-Clients
This.broadcast($ws;$message.data)

Function onOpen($ws : 4D.WebSocketConnection; $message : Object)
// Sende eine Nachricht an den neu verbundenen Benutzer 
$ws.send("Willkommen im Chat!")
// Sende Nachricht "Neuer Client verbunden" an alle anderen Chat-Clients
This.broadcast($ws; "Neuer Client verbunden")

Function onTerminate($ws : 4D.WebSocketConnection; $message : Object)
// Nachricht "Client disconnected" an alle anderen Chat-Clients senden
This.broadcast($ws; "Client disconnected")

Function broadcast($ws : 4D.WebSocketConnection; $message : Text)
var $client:4D.WebSocketConnection
// sendet die Nachricht an alle Chat-Clients
For each ($client; $ws.wss.connections)
// prüft, ob die ID nicht die aktuelle Verbindung ist
If ($client.id#$ws.id)
$client.send($message)
End if 
End for each 

Nun müssen wir nur noch den Websocket-Server mit den oben erstellten Klassen starten. Ein Websocket-Server muss in einem Worker gestartet werden, also erstellen wir einen neuen Prozess mit dem Befehl CALL WORKER und instanziieren den 4D.WebSocketServer darin:

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

CALL WORKER("WebSocketServer"; Formula(WSS:=4D.WebSocketServer.new($handler)))
//Weisen Sie dem WebSocket eine Variable (WSS) zu, damit Sie anschließend WSS.terminate() aufrufen können

Der erstellte Websocket-Server bleibt bestehen, bis der Worker beendet oder die Funktion .terminate() aufgerufen wird.

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

Client-seitig

Nachfolgend finden Sie ein Beispiel für einen Code in HTML und Javascript zur Erstellung einer Chat-Schnittstelle:

Dieser Code ist darauf ausgelegt, mit einem lokalen Webserver am HTTP-Port 80 zu arbeiten (Zeile 18: const urlwss=“ws://127.0.0.1:80/“;).

Schauen Sie sich diese Funktion mit dem obigen HDI an und lesen Sie die Dokumentation für weitere Details!

Fabrice Mainguené
- Product Owner -Fabrice Mainguené gehört seit November 2016 zum 4D Program Team. Als Product Owner ist er verantwortlich für das Schreiben der User Stories und deren Umsetzung in funktionale Spezifikationen. Seine Aufgabe ist es auch, sicherzustellen, dass die gelieferte Funktionsimplementierung den Kundenanforderungen entspricht.Nach seinem Bachelor-Abschluss in Informatik am CNAM arbeitete Fabrice als Windev-Entwickler bei einem kleinen Software-Verlag. Danach arbeitete er für verschiedene Unternehmen in Industrie und Handel als Windev- und Webentwickler sowie als technischer Berater für neue Funktionen.