Comunicaciones TCP/IP en Xojo

Con Xojo resulta realmente sencillo crear aplicaciones que se comuniquem mediante TCP/IP; por ejemplo, para comunicarse con otras aplicaciones en la misma red local o bien con aplicaciones y equipos ubicados a miles de kilómetros. Esto es lo que se puede realizar mediante la clase TCPSocket en Xojo, y que permite tanto enviar como recibir datos utilizando el protocolo de Internet TCP/IP. A continuación se reproduce en Castellano la entrada publicada originalmente en inglés en el área de desarrolladores del sitio web de Xojo y que puedes encontrar en este enlace.

TCPSocket es una subclase de la clase SocketCore, la cual supone la clase base para múltiples clases de red.

Puede utilizarse TCPSocket para comunicar con otros ordenadores de la misma red. Cuando estás conectado a Internet, entonces formas parte de la red de Internet. Esto te permite comunicar con otros ordenadores en Internet mediante TCP/IP.

Configuración

Para iniciar la comunicación TCP/IP necesitas añadir una clase TCPSocket a tu proyecto. El modo más sencillo de hacerlo es arrastrando un control TCPSocket desde la Librería hacia la ventana del Navegador.

Antes de que puedas establecer una conexión con otro ordenador mediante TCPSocket, has de configurar previamente el puerto. El puerto es al TCP/IP lo mismo que podrían ser los canales a un televisor o la asignación de frecuencias a las emisoras de radio. Los puertos proporcionan a las aplicaciones la capacidad de enfocarse en una serie de datos específicos en ves de recibir todos los datos transmitidos a tu ordenador mediante TCP/IP. Esto permite, por ejemplo, navegar por la Web y enviar correo electrónico al mismo tiempo dado que la web utiliza un puerto y el email utiliza otro. El puerto está representado por un número y hay cientos de ellos disponibles como puertos. Algunos de estos números de puerto ya están asignados a funciones concreatas, como por ejemplo la navegación web (80), el email (25, 110 y 143), FTP (20, 21), etc. Si estás diseñando una aplicación que necesitará comunicarse con otra aplicación, entonces tendrás que encontrar qué puerto está utilizando la otra aplicación.

Un TCPSocket tiene una propiedad de puerto que puede asignarse en tiempo de diseño o bien en tiempo de ejecución, pero en cualquier caso debe de tener un valor antes de que puedas conectarte a otro equipo. Si vas a iniciar la conexión, entonces también has de indicar la dirección (IP o nombre resoluble) del ordenador al que te quieres conectar.

Los sistemas operativos Linux y macOS cuentan con una serie de restricciones por omisión sobre la asignación de números de puerto. Los puertos bajo 1024 no pueden ser asignados por un usuario que no esté utilizando el equipo con privilegios de “root”. El sistema operativo macOS está configurado de tal modo que un usuario no puede obtener privilegios root desde la interfaz gráfica de usuario. La mayoría de los usuarios emplean privilegios de administrador (Admin), no root, de modo que deberías de utilizar valores de puerto por encima de 1024 para las comunicaciones normales con macOS o Linux, dado que TCPSocket no puede acceder a números de puerto inferiores a 1024. No se trata de un bug, sino de una característica de seguridad que está incorporada en dichos sistemas operativos.

Un control TCPSocket sólo puede conectarse a una aplicación cada vez. si necesitas mantener múltiples conexiones de forma simultánea, entonces deberás de utilizar la clase ServerSocket, diseñada para tal propósito.

Conectar con otro ordenador

Una vez que has asignado un puerto y una dirección IP puedes conectar a una aplicación a un equipo sobre dicha dirección IP, siempre y cuando la aplicación esté a la escucha de conexiones TCP/IP para el puerto indicado. Para iniciar una conexión has de llamar al método Connect. Recuerda que la conexión no se establece de inmediato necesariamente tras llamar a Connect. Has de esperar a que la aplicación a la que estás intentando conectar acepte tu conexión. Además, también podría haber latencia o bien algunos otros problemas que precisan de algún tiempo en su resolución.

TCPConnection.Connect

Hay dos modos para determinar si estás conectado. Puedes esperar hasta recibir el evento Connecterd desde tu TCPSocket o bien comprobar el valor devuelto por el método IsConnected. Si no esperas por esta información, puedes causar bien la detención del proceso de conexión, resultando en un error de conexión perdida (102) o bien puedes obtener un error de fuera de estado (106).

Cuando se establece la conexión se llama al manejador de evento Connected. Si no se establece una conexión ocurre un error y se llama al manejador de evento Error. Una vez se establece la conexión, tu aplicación puede comenzar a envar y recibir datos con la aplicación situada en el otro extremo de la conexión.

Escuchar por una conexión desde el otro equipo

Tu aplicación también puede escuchar por una petición de conexión por parte de otra aplicación. Para ello, utiliza el método Listen de TCPSocket:

TCPConnection.Listen

Una vez que tienes el TCPSocket en modo de escucha este espera de forma asíncrona a recibir una petición de conexión. Tu aplicación seguirá mostrándose ágil mientras que el socket está esperando, lo que significa que el código continuará ejecutándose.

Cuando se reciba una petición de conexión se llamará al manejador de evento Connected, permitiéndote saber que tienes una conexión.

Leer Datos

Cuando la aplicación situada en el otro extremo de la conexión envía datos hacia el TCPSocket con el que se encuentra conectada se dispara el manejador de evento DataAvailable. Los datos enviados se reciben en una memoria intermedia del ordenador denominada buffer. El buffer es simplemente una ubicación en la cual almacenar los datos enviados por la otra aplicación.

En el manejador de evento DataAvailable puedes utilizar los métodos Read o ReadAll para obtener los datos de forma parcial o bien todos los datos (devueltos como una String) en el buffer. Usa el método Read cuando quieras obtener una cantidad concreta de bytes (caracteres) desde el buffer. Si quieres obtener todos los datos del buffer, debes de utilizar el método ReadAll. En ambos casos, los datos devueltos desde el buffer se eliminan del mismo para hacer hueco en la recepción de nuevos datos entrantes. Si necesitas examinar los datos en el buffer sin eliminarlos del mismo, utiliza el método LookAhead.

Este ejemplo en el manejador de evento DataAvailable adjunta los datos recibidos al TextField:

TextField1.AppendText(Me.ReadAll)

Cuando estás leyendo texto desde una fuente externa es probable que debas de indicar la codificación de texto. La codificación de texto es el esquema que mapea cada letra del texto a un código numérico. Si el texto proviene de otra aplicación, sistema operativo o bien está en otro lenguaje, entonces es probable que debas de indicar la codificación a usar.

Los métodos Read y ReadAll de la clase TCPSocket pueden utilizar un parámetro opcional que permite indicar la codificación. Utiliza el objeto Encodings para obtener la codificación deseada y pasarla como parámetro. Por ejemplo, el código anterior se ha modificado para indicar que el texto entrante utilice la codificación ANSI, un estandar en Windows:

TextField1.AppendText(Me.ReadAll(Encodings.WindowsANSI))

Escribir datos

Puedes enviar datos en cualquier momento a la aplicación a la que estás conectado. Puedes enviar datos usando el método Write. Los datos que desees enviar han ser de tipo string. En este ejemplo se envía el contenido de un TextField mediante un control TCPSocket:

TCPConnection.Write(TextField1.Text)

Si necesitas enviar el texto a una aplicación que esté esperando una codificación de texto concreta entonces deberás de convertir el texto a dicha codificación antes de enviarlo. Usa la función ConvertEncoding para ello. Sus parámetros son el texto a convertir y la codificación de texto a usar. Por ejemplo, la siguiente línea usa el texto en el TextField usando la codificación MacRoman:

TCPConnection.Write(ConvertEncoding(TextField1.Text, Encodings.MacRoman))

Una vez se hayan enviado todos los datos, se invoca el manejador de evento SendComplete. A medida que se envían los datos se invoca el manejador de evento SendProgress, de modo que puedas saber cuantos datos se han enviado. Nunca asumas cuantos datos se envían entre llamadas al evento SendProgress. Es normal que fluctúe.

Si vas a enviar pequeños fragmentos de datos por la red (especialmente en una red pequeña), puede que tenga más sentido usar la clase UDPSocket.

Manejar Errores

Pueden ocurrir errores cuando se intenta realizar una conexión o bien al enviar o recibir datos. Los errores no son siempre lo que parecen. Por ejemplo, cuando el otro ordenador cierra la conexión se genera un error. Cuando ocurre un error se dispara el manejador de eventos Error. Los errores se representan por números. La propiedad LastErrorCode contiene el número del último error ocurrido. Consulta la clase SocketCore para obtener un listado completo de los números de error.

Los errores son simplemente modos de avisar a tu aplicación de las condiciones que no han podido anticiparse.

Cerrar la conexión

Cuando has finalizado con la comunicación y deseas desconectarte de la otra aplicación puedes hacerlo cerrando la conexión. Se cierra la conexión llamando al método Close de TCPSocket. Supongamos que tienes un Socket con el nombre “TCPConnection” que ha establecido una conexión. Para cerrar la conexión, puedes usar el siguiente código:

TCPConnection.Close

Otra información de Socket

Destruir un Socket

Cuando llamas los métodos Listen o Connect, se incrementa el contador de referencias del socket.

Esto significa que el socket no necesita ser propiedad de nada (como una Ventana) para que siga funcionando. Esto es útil en ciertas condiciones. Por ejemplo, supongamos que escribes tu propia subclase socket que implemente todos los eventos del socket, denominado MySocket. En el evento de acción de un Button puedes usar el siguiente código:

Dim s As New TCPSocket
s.Port = 7000
s.Address = "127.0.0.1"
s.Listen

Incluso una vez que se complete este evento el socket permanece activo a la escucha de conexiones. De hecho, el socket permanece activo y vivo hasta que lo cierres de forma específica cerrando la conexión localmente o de forma remota.

Por supuesto, el socket también se cerrará una vez que se salga de la aplicación.

Seguridad

Se utiliza la clase SSLSocket para realizar comunicaciones seguras mediante TCP/IP. Funciona de forma similar a la clase TCPSocket, pero tiene propiedades adicionales para el tipo de conexión, gestión del certificado y la comprobación de que se haya realizado una conexión segura.

2 comentarios en “Comunicaciones TCP/IP en Xojo

  1. Jose M E Llaras Jordana

    Necesito abrir puerta salto

    Desde un programa en pyton

    Atraves tcp.ip

    1. Javier Rodriguez

      Estimado Jose,
      Este sitio web y todos sus contenidos se centran en la programación multiplataforma con Xojo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *