Nouvelle classe pour gérer les connexions TCP entrantes

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.

HDI TCPConnexions

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.

Nicolas Brachfogel
- Product Owner & Senior Developer - Nicolas Brachfogel a rejoint 4D en 2017 en tant que développeur senior (4D Server et networking) et en tant que Product Owner pour gérer la mise en production d'Apple Silicon. Il est chargé de rédiger les user stories et de les traduire en spécifications fonctionnelles, ainsi que de s'assurer que les implémentations des fonctionnalités répondent aux besoins des clients. Diplômé de l'Institut Supérieur d'Informatique Appliquée (INSIA), Nicolas a commencé sa carrière en tant que développeur de logiciels en 2001. Après plusieurs années de programmation en Java et C++, il s'est spécialisé dans le développement client-serveur pour des sociétés de jeux vidéo. En tant que développeur/architecte serveur, il a travaillé avec succès sur les architectures serveur de nombreux jeux (Dofus Arena, Drakerz, Trivial Pursuit Go !).