Nouvelle classe pour les communications UDP

4D 20 R8 a introduit la classe TCPConnection, qui offre un moyen orienté objet et asynchrone de gérer les connexions des clients TCP. Ensuite, 4D 20 R9 a introduit la classe TCPListener pour construire des serveurs TCP. Et maintenant, avec 4D 20 R10, nous complétons le tableau avec la nouvelle classe UDPSocket, vous permettant de gérer les communications UDP entre 4D et n’importe quelle machine distante, à la fois en tant que client et en tant que serveur. Ceci est particulièrement utile pour l’IoT, la surveillance en temps réel ou le broadcasting. Et la cerise sur le gâteau ? Cette classe supporte les communications UDP préemptives et asynchrones.
Enfin, cette nouvelle fonctionnalité marque l’étape finale du remplacement de l’ancien plugin Internet Commands.
Entrons dans les détails.

Pourquoi UDP ?

UDP est un protocole léger, sans connexion. Contrairement à TCP, il ne maintient pas de connexion persistante entre les deux points d’extrémité. Il n’y a pas de mécanisme intégré d’accusé de réception ou de retransmission, ce qui le rend utile pour les scénarios « envoyer et oublier » imposés par des tiers, comme l’IoT, la surveillance en temps réel ou le broadcasting.
Avec la nouvelle classe UDPSocket, vous disposez désormais d’un contrôle total sur l’envoi et la réception de paquets UDP dans 4D. Les principes présentés ci-dessous sont également décrits dans ce HDI :

HDI UDPSocket

Définition d’une classe client UDP

Voici une classe clientUDP simple qui gère l’envoi de données à un serveur 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")

Dans cet exemple :

  • Le constructeur définit l’IP et le port cibles.
  • La fonction sendMessage envoie le message passé en paramètre.
  • onError et onTerminate gèrent les événements du cycle de vie.
  • Aucun onData n’est nécessaire : les clients UDP ne reçoivent généralement pas de réponse.

 

Définition d’une classe de serveur UDP

Examinons maintenant une classe serverUDP qui écoute les messages UDP entrants :

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")

Ici :

  • Le serveur écoute sur le port donné comme paramètre du constructeur.
  • La fonction de retour onData gère les messages entrants. Les messages sont stockés dans une instance de la nouvelle classe UDPEvent.
  • Comme pour le client, onError et onTerminate gèrent les événements du cycle de vie.

 

Exécution du serveur dans un WORKER

Pour que le serveur fonctionne de manière indépendante, vous devez le lancer dans un worker :

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

Note : Le socket UDP est automatiquement libéré lorsqu’il n’y a plus de référence sur l’objet. Dans ce cas, l’arrêt du worker mettra fin au serveur.

Envoi de données du client au serveur

Une fois les deux classes en place, l’envoi d’un message est aussi simple que :

cs.clientUDP.new("127.0.0.1" ; 12345).sendMessage("Message de test")
La communication UDP n’a jamais été aussi simple dans 4D. Grâce à la nouvelle classe UDPSocket, vous pouvez désormais intégrer à vos applications des fonctions de communication légères et en temps réel, qu’il s’agisse d’envoyer des commandes à un périphérique ou d’écouter les mises à jour d’un système distant.
Nous espérons que cette nouvelle fonctionnalité ouvrira des perspectives intéressantes pour vos projets.
Il est temps de se débarrasser du plugin Internet Commands !
Bon codage !

Avatar
- Product Owner - Damien Fuzeau a rejoint l'équipe 4D Product en février 2019. En tant que Product Owner, il est en charge de la rédaction des user stories, puis de leur traduction en spécifications fonctionnelles. Son travail consiste également à s'assurer que les implémentations de fonctionnalités livrées répondent aux besoins des clients.Damien est diplômé de l'Université de Nantes en génie logiciel. Il a passé plus de 23 ans dans son ancienne entreprise, d'abord en tant que développeur (découverte de 4D en 1997), puis en tant que responsable de l'ingénierie et architecte logiciel. Cette société est un partenaire OEM de 4D et a déployé des logiciels d'entreprise basés sur 4D pour des milliers d'utilisateurs, sur des centaines de serveurs. Damien est donc habitué au développement et au déploiement 4D dans un contexte multi-langues.