Nueva clase para las comunicaciones UDP

4D 20 R8 introdujo la clase TCPConnection, aportando una forma asíncrona y orientada a objetos de manejar las conexiones de clientes TCP. Luego vino 4D 20 R9 con la clase TCPListener para construir servidores TCP. Y ahora, con 4D 20 R10, estamos completando el cuadro con la nueva clase UDPSocket, que le permite gestionar las comunicaciones UDP entre 4D y cualquier máquina remota, tanto como cliente como servidor. Esto es especialmente útil para IoT, monitorización en tiempo real o intercambios de difusión. ¿Y la cereza del pastel? Esta clase soporta comunicación UDP preventiva y asíncrona.
Por último, esta nueva funcionalidad está marcando el paso final en la sustitución del plugin de comandos de Internet heredado.
Profundicemos en los detalles.

¿Por qué UDP?

UDP es un protocolo ligero y sin conexión. A diferencia de TCP, no mantiene una conexión persistente entre los dos extremos. No lleva intregrado ningún mecanismo de acuse de recibo o retransmisión, lo que lo hace útil para escenarios de «enviar y olvidar» impuestos por terceros, como IoT, monitorización en tiempo real o radiodifusión.
Con la nueva clase UDPSocket, ahora tiene control total sobre el envío y recepción de paquetes UDP en 4D. Los principios presentados a continuación también se describen en este HDI:

HDI UDPSocket

Definición de una Clase Cliente UDP

He aquí una simple clase clienteUDP que maneja el envío de datos a un servidor UDP:

property socket : 4D.UDPSocket
property ip : Text
property port : Integer

Class constructor ($ip: Text; $port: Integer)
This .socket:=4D.UDPSocket.new(0; This)
This .ip:=$ip
This .port:=$port

//Send message to the UDP server
Function sendMessage ($message: Text)

var $blob : Blob
TEXT TO BLOB ($message; $blob; UTF8 text without length)
This .socket.send($blob; This.ip; This.port)

//Callback called when the socket is closed unexpectedly
Function onError ($socket: 4D.UDPSocket; $event: 4D.UDPEvent)

ALERT ("clientUDP instance error")

//Callback called after onShutdown/onError just before the UDPSocket object is released
Function onTerminate($socket : 4D.UDPSocket; $event : 4D.UDPEvent)

ALERT ("clientUDP instance termination")

En este ejemplo:

  • El constructor define la IP y el puerto de destino.
  • La función sendMessage envía el mensaje pasado en parámetro.
  • onError y onTerminate manejan los eventos del ciclo de vida.
  • No es necesario onData: los clientes UDP normalmente no reciben respuestas.

 

Definiendo una Clase Servidor UDP

Ahora veamos una clase serverUDP que escucha los mensajes UDP entrantes:

property socket 4D .UDPSocket

//The constructor creates a UDPSocket to listen to the port given in parameter
Class constructor ($port: Integer)

This .socket:=4D.UDPSocket.new($port; This)

//Callback called when receiving data
Function onData ($socket: 4D.UDPSocket; $event: 4D.UDPEvent)

var $data :=BLOB to text($event.data; UTF8 text without length)

ALERT ("serverUDP instance: Received message:\r\n "+$data)

//Callback called when the connection is closed unexpectedly
Function onError ($socket: 4D.UDPSocket; $event: 4D.UDPEvent)

ALERT ("serverUDP instance: error\r\n "+JSON Stringify($event.data; *))

//Callback called after onShutdown/onError just before the UDPSocket object is released
Function onTerminate ($socket: 4D.UDPSocket; $event: 4D.UDPEvent)

ALERT ("serverUDP instance: Server termination")

Aquí:

  • El servidor escucha en el puerto dado como parámetro del constructor.
  • La llamada de retorno onData gestiona los mensajes entrantes. Los mensajes se almacenan en una instancia de la nueva clase UDPEvent.
  • Al igual que con el cliente, onError y onTerminate gestionan los eventos del ciclo de vida.

 

Ejecutar el Servidor en un Worker

Para mantener el servidor funcionando de forma independiente, debe lanzarlo en un worker:

CALL WORKER("miServidorUDP"; Formula(cs.serverUDP.new(12345)))

Nota: el socket UDP se libera automáticamente cuando no hay más referencia en el objeto. En este caso, al detener el worker se terminará el servidor.

Envío de datos del cliente al servidor

Una vez que ambas clases están en su lugar, enviar un mensaje es tan simple como:

cs.clientUDP.new("127.0.0.1"; 12345).sendMessage("Mensaje de prueba")
La comunicación UDP nunca ha sido tan fácil en 4D. Con la nueva clase UDPSocket, ahora puede construir funciones de comunicación ligeras y en tiempo real en sus aplicaciones, ya sea que esté enviando comandos a un dispositivo o escuchando actualizaciones de un sistema remoto.
Esperamos que esta nueva función abra interesantes posibilidades para sus proyectos.
Es hora de deshacerse del plugin Internet Commands.
¡Feliz programación!

Avatar
• Propietario de producto - Damien Fuzeau se ha unido al equipo de 4D Product en febrero de 2019. Como Propietario de producto, está a cargo de escribir historias de usuario, y luego traducirlas a especificaciones funcionales. Su trabajo también implica asegurarse de que las implementaciones de funcionalidades entregadas estén cumpliendo con las necesidades del cliente. Damien es licenciado en ingeniería de software por la Universidad de Nantes. Estuvo más de 23 años en su anterior empresa, primero como desarrollador (descubriendo 4D en 1997), y más tarde como gerente de ingeniería y arquitecto de software. Esta compañía es un Partner OEM de 4D y ha desplegado softwares empresariales basados en 4D para miles de usuarios, en cientos de servidores. Por lo tanto, Damien está acostumbrado al desarrollo y despliegue de 4D en un contexto multilingüe.