En 4D 20 R8, introdujimos la clase TCPConnection, permitiéndole iniciar conexiones TCP a servidores remotos. Con 4D v20 R9, estamos entusiasmados de traerle la clase TCPListener, la llave para manejar conexiones TCP entrantes y construir un servidor TCP directamente en 4D.
Con estas dos clases-TCPConnection y TCPListener-usted tiene ahora control total sobre la comunicación TCP, tanto del lado del cliente como del lado del servidor.
Veamos cómo utilizarlas juntas.
Antes de entrar de lleno en este artículo, le recomendamos que le dé un vistazo a nuestro artículo anterior sobre la clase TCPConnection para entender la base sobre la que estamos construyendo.
Cómo interactúan las clases TCPListener y TCPConnection
Definición de la clase DE conexión
Crearemos una nueva clase llamada ServerSideConnection, siguiendo el modelo de la clase ConnectionToTheServer utilizada en el ejemplo anterior. Aquí tiene un desglose de las principales retrollamadas que implementará:
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")
Esta clase es un sencillo intérprete de comandos que reacciona a los principales eventos TCP.
Configuración de la clase Listener
Ahora, vamos a crear una clase ServerListener para escuchar en un puerto específico y aceptar conexiones 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")
Para iniciar el listener, usa:
cs.ServerListener.me.startListening($port)
Cada vez que un cliente intenta conectarse, el método onConnection es disparado. Puede devolver un objeto ServerSideConnection para aceptar la conexión o devolver null para rechazarla. Una vez aceptada, se activan las correspondientes retrollamadas TCPConnection, permitiéndote manejar la conexión como cualquier otro cliente.
Para dejar de escuchar nuevas conexiones, simplemente llame:
cs.ServerListener.me.stopListening()
Nota: las conexiones activas permanecerán hasta que las cierre manualmente.
Estructura de clases unificada = Código simplificado
Uno de los principales beneficios de este diseño es que la misma clase TCPConnection se utiliza tanto para conexiones cliente como servidor. Esta simetría simplifica su implementación y promueve la reutilización de código, ya que el comportamiento para ambos extremos de la conexión puede compartir la misma lógica y estructura.
Conclusión
Con la adición de la clase TCPListener en 4D v20 R9, ahora puede crear robustos servidores TCP completamente en 4D. Junto con TCPConnection, las nuevas herramientas le dan un marco de trabajo completo para manejar la comunicación TCP bidireccional, de manera limpia, eficiente y con mínima duplicación de código.
Si tiene alguna pregunta o comentario, no dude en plantearlo en el foro de 4D.