Dans 4D 20 R8, nous avons introduit la classe TCPConnection, qui vous permet d’initier des connexions TCP vers des serveurs distants. Avec 4D v20 R9, nous sommes ravis de vous présenter la classe TCPListener, la clé pour gérer les connexions TCP entrantes et construire un serveur TCP directement dans 4D.
Avec ces deux classes – TCPConnection et TCPListener – vous avez maintenant un contrôle total sur la communication TCP, à la fois côté client et côté serveur.
Voyons comment les utiliser ensemble.
Avant de plonger dans cet article, nous vous recommandons vivement de consulter notre précédent article de blog sur la classe TCPConnection afin de comprendre les bases sur lesquelles nous nous appuyons.
Comment les classes TCPListener et TCPConnection interagissent
Définition de la classe de connexion
Nous allons créer une nouvelle classe appelée ServerSideConnection, calquée sur la classe ConnectionToTheServer utilisée dans l’exemple précédent. Voici un aperçu des principaux callback que vous allez implémenter :
Class constructor()
//Callback called when the connection is successfully established
Function onConnection($connection : 4D.TCPConnection; $event : 4D.TCPEvent)
ALERT("Connection established")
//Callback called when the connection is properly closed
Function onShutdown($connection : 4D.TCPConnection; $event : 4D.TCPEvent)
ALERT("Connection closed")
//Callback called when receiving data. The simple servers always send a sentence to show to the user
Function onData($connection : 4D.TCPConnection; $event : 4D.TCPEvent)
ALERT(BLOB to text($event.data; UTF8 text without length))
//Callback called when the connection is closed unexpectedly
Function onError($connection : 4D.TCPConnection; $event : 4D.TCPEvent)
ALERT("Connection error")
Cette classe réagit aux principaux événements TCP.
Mise en place de la classe listener
Créons maintenant une classe ServerListener pour écouter sur un port spécifique et accepter les connexions entrantes :
property listener:4D.TCPListener
shared singleton Class constructor()
//Start listening to the port given as parameter
shared Function startListening($port:integer)
This.listener:=4D.TCPListener.new($port, This)
//Stop listening
shared Function stopListening()
This.listener.terminate()
//Callback called on a new incoming connection
Function onConnection($listener : 4D.TCPListener; $event : 4D.TCPEvent)->$result
ALERT("Listener: onConnection")
if ($event.IP = "a good IP address")
$result:=cs.ServerSideConnection.new()
else
$result := null
end if
//Callback called when an error prevents listening on the port (in general due to conflict with another application)
Function onError($listener : 4D.TCPListener; $event : 4D.TCPEvent)
ALERT("Listener: onError")
Pour démarrer le listener, utilisez :
cs.ServerListener.me.startListening($port)
Chaque fois qu’un client tente de se connecter, la méthode onConnection est déclenchée. Vous pouvez renvoyer un objet ServerSideConnection pour accepter la connexion ou renvoyer null pour la rejeter. Une fois la connexion acceptée, les callbacks de TCPConnection correspondants sont activés, ce qui vous permet de gérer la connexion comme n’importe quelle autre.
Pour cesser d’écouter les nouvelles connexions, il suffit d’appeler :
cs.ServerListener.me.stopListening()
Remarque : les connexions actives sont maintenues jusqu’à ce que vous les fermiez manuellement.
Structure de classe unifiée = code simplifié
L’un des principaux avantages de cette conception est que la même classe TCPConnection est utilisée pour les connexions client et serveur. Cette symétrie simplifie votre implémentation et favorise la réutilisation du code, car le comportement des deux extrémités de la connexion peut partager la même logique et la même structure.
Conclusion
Avec l’ajout de la classe TCPListener dans 4D v20 R9, vous pouvez désormais créer des serveurs TCP robustes entièrement dans 4D. Associés à TCPConnection, les nouveaux outils vous offrent un cadre complet pour gérer les communications TCP bidirectionnelles, de manière propre, efficace et avec un minimum de duplication de code.
Si vous avez des questions ou des commentaires, n’hésitez pas à les poser sur le forum 4D.