Un ejemplo de implementación de una conversación de texto en tiempo real con la biblioteca SignalR
Autor: Denis Balant, Enej Hudobreznik
El protocolo HTTP (Protocolo de transferencia de hipertexto) todavía se utiliza principalmente para la transferencia de datos a través de Internet. su derivado cifrado HTTPS (HTTP Secure), más moderno y seguro. Se basan en una arquitectura cliente-servidor, donde el cliente (cliente en inglés) envía una solicitud (solicitud HTTP en inglés) al servidor (servidor en inglés) y el servidor responde con una respuesta (respuesta HTTP en inglés).
Los protocolos HTTP y HTTPS son adecuados para transferencias simples de solicitud-respuesta (por ejemplo, transferencia de un archivo HTML a petición del cliente). Utilizando estos dos protocolos, el usuario sólo puede obtener datos actualizados cuando envía una nueva solicitud, por lo que no son los más adecuados para la transferencia de datos en tiempo real (por ejemplo, chat online, videojuegos online, seguimiento de ubicación...), en los que Se basa gran parte de la funcionalidad de las aplicaciones web modernas. La agilidad se puede implementar de muchas maneras diferentes y mejores, cada una con sus propias ventajas y desventajas.
El método de implementación más simple es el sondeo regular, donde el cliente envía repetidamente solicitudes de nuevos datos al servidor en cada intervalo de sondeo, independientemente de si el contenido ha cambiado o no. A pesar de su simplicidad, este enfoque no es adecuado para servicios más grandes donde el acceso al servidor requiere muchos clientes, porque una gran cantidad de solicitudes innecesarias y repetidas pueden sobrecargarlo y así ralentizar el rendimiento del servicio.
La mejora se logra mediante la introducción de un sondeo a largo plazo, donde el cliente envía solicitudes al servidor de la misma manera, pero el servidor no responde hasta que detecta la presencia de nuevos datos. La desventaja de este enfoque es que el cliente debe tener definido un cierto intervalo de tiempo después del cual reconoce la inactividad del servidor como un error. Esto agrega una capa adicional de complejidad a la configuración del cliente y del servidor.
El estándar HTML5 moderno también proporciona una API llamada Eventos enviados por el servidor. Es un protocolo donde el cliente no tiene que enviar solicitudes periódicamente al servidor, sino que el servidor reenvía los datos necesarios cuando se realizan cambios, facilitando así la comunicación en tiempo real.
El estándar HTML5 también ofrece el protocolo WebSockets, que permite una verdadera comunicación bidireccional en tiempo real. Al inicio del establecimiento se realiza un apretón de manos, donde el cliente y el servidor acuerdan el conjunto de estándares que utilizarán. Después de un apretón de manos exitoso, se abre una conexión permanente con un pequeño retraso entre los dos participantes. Este protocolo es especialmente útil cuando se trata de una conexión punto a punto (una conexión directa entre un cliente y un servidor).
Además de la arquitectura clásica cliente-servidor, existen otras soluciones en las que la conexión entre clientes no fluye a través de servidores, sino directamente entre clientes que desempeñan el papel de cliente y servidor (estas redes peer-to-peer). Un protocolo popular para la comunicación en tiempo real en este tipo de redes es WebRTC.
En el entorno .NET para comunicación en tiempo real, podemos usar la biblioteca SignalR de código abierto, que forma parte del marco web ASP.NET Core, por lo que es fácil agregarla a proyectos existentes como un nivel adicional de middleware cuando procesar solicitudes entrantes. La biblioteca simula llamadas a métodos en el cliente desde el lado del servidor y llamadas a métodos en el servidor desde el lado del cliente (llamada a procedimiento remoto - RPC), pero no garantiza la idoneidad del no. parámetros y sus tipos. Desde el servidor podemos llamar a métodos en todos los clientes, en un grupo específico de clientes o en un solo cliente.
Su principal ventaja es la simplicidad de implementación gracias a los paquetes de desarrollo de software (SDK) para muchas plataformas diferentes, que ocultan el funcionamiento interno del servicio a los programadores, y la posibilidad de alojamiento sencillo con el servicio Azure SignalR. Una ventaja adicional es que el propio servicio elige el tipo de conexión más apropiado (descrita anteriormente) entre el cliente y el servidor.
El uso de la biblioteca se basa en clases especiales llamadas hubs, que representan una abstracción de la conexión entre los clientes y el servidor. Para ellos, definimos métodos que los clientes pueden llamar en el servidor.
El siguiente ejemplo muestra un ejemplo de implementación de una conversación de texto simple. Primero, definimos el nodo base para la conversación en el servidor. Los métodos de esta clase representan métodos que los clientes pueden llamar en el servidor. Cuando se llama al método SendMessage, el cliente envía el ID de usuario (userId) y el contenido del mensaje (message), mientras que el servidor llama al método ReceiverMessage en todos los clientes con los parámetros especificados.
El siguiente ejemplo muestra una implementación de cliente web JavaScript utilizando la biblioteca oficial (@microsoft/signalr). Los clientes se conectan a la URL del nodo (/chat en el ejemplo siguiente). Una conexión está representada por el objeto de conexión. El método on representa un oyente de la llamada al método, cuyo nombre se proporciona como primer parámetro y como segundo la función que se ejecuta en el evento. Implementamos métodos en el servidor a través del método de invocación del objeto de conexión, que requiere el nombre del método como primer argumento, seguido de sus parámetros.
De forma predeterminada, los datos se transfieren entre el servidor y los clientes en formato JSON, pero la biblioteca también admite el formato MessagePack, más eficiente.
Aunque la biblioteca facilita enormemente el desarrollo, tiene sus inconvenientes. Uno de los principales es la escalabilidad del sistema para autohospedarse y garantizar un funcionamiento ininterrumpido, ya que su implementación es muy difícil de distribuir en varios servidores separados. Esto resulta especialmente difícil si queremos reducir la latencia para usuarios remotos y alojar en varias ubicaciones diferentes, ya que el diseño de la solución se limita a una sola. Además, la biblioteca no garantiza la entrega y el ordenamiento confiables de los mensajes, lo que puede degradar la experiencia del usuario.