Neue Klasse zur Behandlung eingehender TCP-Verbindungen

In 4D 20 R8 haben wir die Klasse TCPConnection eingeführt, mit der Sie TCP-Verbindungen zu entfernten Servern initiieren können. Mit 4D v20 R9 freuen wir uns, Ihnen die Klasse TCPListener vorstellen zu können – Ihr Schlüssel zur Handhabung eingehender TCP-Verbindungen und zum Aufbau eines TCP-Servers direkt in 4D.

Mit diesen beiden Klassen – TCPConnection und TCPListener – haben Sie nun die volle Kontrolle über die TCP-Kommunikation, sowohl client- als auch serverseitig.

Wir zeigen Ihnen, wie Sie die beiden Klassen zusammen verwenden können.

HDI TCPConnections

Bevor Sie in diesen Beitrag eintauchen, empfehlen wir Ihnen einen Blick in unseren vorherigen Blogbeitrag über die Klasse TCPConnection, um die Grundlagen zu verstehen, auf denen wir aufbauen.

 

Wie die Klassen TCPListener und TCPConnection zusammenspielen

Definieren der Verbindungsklasse

Wir erstellen eine neue Klasse namens ServerSideConnection, die sich an der Klasse ConnectionToTheServer orientiert, die im vorherigen Beispiel verwendet wurde. Im Folgenden finden Sie eine Aufschlüsselung der wichtigsten Callbacks, die Sie implementieren werden:

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

Diese Klasse ist eine unkomplizierte Shell, die auf wichtige TCP-Ereignisse reagiert.

Einrichten der Listener-Klasse

Erstellen wir nun eine ServerListener-Klasse, die auf einem bestimmten Port lauscht und eingehende Verbindungen annimmt:

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

Um den Listener zu starten, verwenden Sie:

cs.ServerListener.me.startListening($port)

Jedes Mal, wenn ein Client versucht, eine Verbindung herzustellen, wird die Methode onConnection ausgelöst. Sie können ein ServerSideConnection-Objekt zurückgeben, um die Verbindung zu akzeptieren, oder null zurückgeben, um sie abzulehnen. Sobald die Verbindung akzeptiert wurde, werden die entsprechenden TCPConnection-Callbacks ausgelöst, so dass Sie die Verbindung wie jeden anderen Client behandeln können.

Um das Warten auf neue Verbindungen zu beenden, rufen Sie einfach auf:

cs.ServerListener.me.stopListening()

Hinweis: Aktive Verbindungen bleiben bestehen, bis Sie sie manuell schließen.

Vereinheitlichte Klassenstruktur = Vereinfachter Code

Ein großer Vorteil dieses Designs ist, dass dieselbe TCPConnection-Klasse sowohl für Client- als auch für Server-Verbindungen verwendet wird. Diese Symmetrie vereinfacht Ihre Implementierung und fördert die Wiederverwendung von Code, da das Verhalten für beide Enden der Verbindung dieselbe Logik und Struktur haben kann.

Schlussfolgerung

Mit der Hinzufügung der TCPListener Klasse in 4D v20 R9 können Sie nun robuste TCP Server vollständig in 4D erstellen. Zusammen mit TCPConnection bieten Ihnen die neuen Tools ein komplettes Framework für die Handhabung von Zwei-Wege-TCP-Kommunikation – sauber, effizient und mit minimaler Code-Duplizierung.

Wenn Sie Fragen oder Feedback haben, zögern Sie nicht, diese im 4D Forum zu stellen.

Nicolas Brachfogel
Product Owner & Senior Developer - Nicolas Brachfogel kam 2017 als Senior Developer (4D Server und Netzwerke) zu 4D. Als Product Owner, der die Freigabe von Apple Silicon verwaltet, ist er für das Schreiben von User Stories und deren Umsetzung in funktionale Spezifikationen zuständig und stellt sicher, dass die Implementierungen der Funktionen den Kundenanforderungen entsprechen. Nicolas ist Absolvent des Institut Supérieur d'Informatique Appliquée (INSIA) und begann seine Karriere als Softwareentwickler im Jahr 2001. Nachdem er mehrere Jahre in Java und C++ programmiert hatte, spezialisierte er sich auf die Client-Server-Entwicklung für Videospielunternehmen. Als Server-Entwickler/Architekt arbeitete er erfolgreich an den Server-Architekturen vieler Spiele (Dofus Arena, Drakerz, Trivial Pursuit Go!).