Nuevo servidor Websocket integrado

En un mundo cada vez más conectado, los sitios web o las aplicaciones IoT deben actualizarse en tiempo real.

Una forma de entregar información instantáneamente a sus sitios es utilizar el protocolo Websocket que ofrece un canal de comunicación full-duplex entre un servidor y un cliente. Desde la v20, 4D ofrece comandos para crear un servidor Websocket.

Comandos para crear un servidor Websocket

Para gestionar su servidor websocket, 4D ofrece dos nuevas clases:

  • La primera gestiona el propio servidor, 4D.WebSocketServer
  • La segunda gestiona las conexiones websocket: 4D.WebSocketConnection

 

Para demostrar esta funcionalidad, vamos a crear un simple servidor de chat.

Antes de usar la clase servidor websocket, ¡Su servidor web 4D debe estar iniciado!

4D.WebSocketServer

Esta clase le permite manejar diferentes eventos que ocurren en su servidor. Para ello, necesita crear una clase con las siguientes funciones:

  • onConnection(), llamada cuando se solicita una nueva conexión.
  • onOpen(), llamada cuando se inicia el servidor
  • onTerminate(), llamada cuando el servidor se detiene
  • onError(), llamada cuando se produce un error.

En nuestro ejemplo, primero tenemos que gestionar la solicitud de conexión. Con la función onConnection(), puede cancelar una conexión devolviendo Null o un objeto que se utilizará para gestionar el mensaje enviado o recibido. En el siguiente ejemplo, devolvemos la clase WSConnectionHandler (descrita en la siguiente sección):

Function onConnection($wss : Objeto; $param : Objeto) : Object
 // llamar al método VerifyAddress para verificar si la dirección remota permite la conexión
If (VerifyAddress($param.request.remoteAddress))
// La conexión es permitida
// El objeto WSConnectionHandler devuelto es utilizado 
// por 4D para instanciar el objeto 4D.WebSocketConnection
// relacionado con esta conexión
return cs.WSConnectionHandler.new() 
Else 
// La conexión se cancela
return Null 
End if 

Ahora, queremos registrar el inicio, cierre y errores, así que creamos una clase WSServerHandler:

Constructor de la clase

Function onOpen($wss : Object; $param : Object)
LogFile("*** Servidor iniciado")

Function onTerminate($wss : Object; $param : Object)
LogFile("*** Servidor cerrado")

Function onError($wss : Object; $param : Object)
LogFile("!!! Error de servidor: "+$param.statusText)

4D.WebSocketConnection

Esta clase permite gestionar diferentes eventos durante una determinada conexión. Para ello, es necesario crear una clase con las siguientes funciones:

  • onMessage(), llamada cada vez que llega un mensaje a través de esta conexión.
  • onOpen(), llamada cuando se crea el objeto 4D.WebSocketConnection
  • onTerminate(), llamada cuando se termina el objeto 4D.WebSocketConnection
  • onError(), llamada cuando se produce un error

 

Para hacer nuestro chat, esta clase será la clase WSConnectionHandler. Esta clase

  • avisa a otros usuarios de que un nuevo usuario está conectado cuando se abre la conexión
  • avisa a los demás usuarios de que un usuario se ha desconectado cuando se termina la conexión
  • difunde los mensajes recibidos a todos los demás clientes de chat conectados cuando se recibe un mensaje.

 

Function onMessage($ws : 4D.WebSocketConnection; $message : Object)
// reenviar el mensaje a todos los clientes de chat
This.broadcast($ws;$message.data)

Function onOpen($ws : 4D.WebSocketConnection; $message : Object)
// Enviar un mensaje al nuevo usuario conectado 
$ws.send("¡Bienvenido al chat!")
// Enviar el mensaje "Nuevo cliente conectado" a todos los demás clientes del chat
This.broadcast($ws; "Nuevo cliente conectado")

Function onTerminate($ws : 4D.WebSocketConnection; $message : Object)
// Enviar mensaje "Cliente desconectado" a todos los demás clientes del chat
This.broadcast($ws; "Cliente desconectado")

Function broadcast($ws : 4D.WebSocketConnection; $message : Text)
var $client:4D.WebSocketConnection
// reenviar el mensaje a todos los clientes del chat
For each ($client; $ws.wss.connections)
// Verificar que el id no es la conexión actual
If ($client.id#$ws.id)
$client.send($message)
End if 
End for each 

Todo lo que queda es iniciar el servidor websocket usando las clases creadas anteriormente. Un servidor websocket debe iniciarse en un worker, así que creamos un nuevo proceso con el comando CALL WORKER e instanciamos el 4D.WebSocketServer en él:

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

CALL WORKER("WebSocketServer"; Formula(WSS:=4D.WebSocketServer.new($handler)))
//Asignar una variable (WSS) al WebSocket permite llamar después a WSS.terminate()

El servidor websocket creado existirá hasta que el trabajador sea eliminado o se llame a la función .terminate().

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

Del lado del cliente

A continuación puede encontrar un ejemplo de código en HTML y Javascript para crear una interfaz de chat:

Este código está diseñado para funcionar con un servidor web local en el puerto HTTP 80 (línea 18: const urlwss=»ws://127.0.0.1:80/»;).

Consulte esta función con el IDH anterior y la documentación para obtener más detalles.

Fabrice Mainguené
- Product Owner -Fabrice Mainguené se unió al equipo de 4D Program en noviembre de 2016. Como Product Owner, está a cargo de escribir las historias de usuario y luego traducirlas a especificaciones funcionales. Su papel es también asegurarse de que la implementación de la característica entregada cumple con las necesidades del cliente. Después de obtener una licenciatura en Ciencias de la Computación en el CNAM, Fabrice se unió a una pequeña empresa de publicación de software como desarrollador Windev. A continuación, trabajó para diferentes empresas del sector industrial y comercial como desarrollador de Windev y de la web, así como asesor técnico de nuevas funcionalidades.