Software
20.08.2024 08:35

Share with others:

Share

An example of implementing a real-time text conversation with the SignalR library

Despite the constant evolution of websites, the underlying technologies have remained very similar over time. Since the web is not only home to modern sites, but also to older ones that must also work in modern browsers, today's technologies are often only improved and supplemented versions of those that were created at the very beginning of the world wide web. More advanced modern functions, which are not supported by this solution, are made possible by new standards.
The photo is illustrative. (Photo: Pixabay)
The photo is illustrative. (Photo: Pixabay)

Author: Denis Balant, Enej Hudobreznik


The HTTP (Hypertext Transfer Protocol) protocol is still primarily used for data transfer over the Internet. its more modern and safer encrypted derivative HTTPS (HTTP Secure). They are based on a client-server architecture, where the client (English client) sends a request (English HTTP request) to the server (English Server), and the server responds to it with a response (English HTTP response).

HTTP requests and responses (source: https://www.telerik.com/blogs/real-time-communication-techniques)
HTTP requests and responses (source: https://www.telerik.com/blogs/real-time-communication-techniques)

The HTTP and HTTPS protocols are suitable for simple request-response transfers (e.g. transfer of an HTML file at the client's request). Using these two protocols, the user can get updated data only when he sends a new request, so they are not the most suitable for real-time data transfer (eg online chat, online video games, location tracking... ), on which much of the functionality of modern web applications is based. Agility can be implemented in many different and better ways, each with its own advantages and disadvantages.

The simplest method of implementation is regular polling, where the client repeatedly sends requests for new data to the server every polling interval, regardless of whether the content has changed at all. Despite its simplicity, this approach is not suitable for larger services where access to the server requires many clients, because a large amount of unnecessary and repeated requests can overload it and thus slow down the performance of the service.

Real-time interrogation (source: https://www.telerik.com/blogs/real-time-communication-techniques)

The improvement is achieved by introducing long-term polling, where the client sends requests to the server in the same way, but the server does not respond to them until it detects the presence of new data. The disadvantage of such an approach is that the client must have a certain time interval defined, after which it recognizes the server's inactivity as an error. This adds an extra layer of complexity to the client and server setup.

Long-term interrogation (source: https://www.telerik.com/blogs/real-time-communication-techniques)

The modern HTML5 standard also provides an API called Server-Sent Events. It is a protocol where the client does not have to periodically send requests to the server, but the server resends the necessary data when changes are made, thus facilitating real-time communication.

Server-Sent Events (source: https://www.telerik.com/blogs/real-time-communication-techniques)

The HTML5 standard also offers the WebSockets protocol, which enables true two-way real-time communication. At the beginning of the establishment, a handshake is performed, where the client and the server agree on the set of standards that they will use. After a successful handshake, a permanent connection with a small delay is opened between the two participants. This protocol is especially useful when it comes to a point-to-point connection (a direct connection between a client and a server).

In addition to the classic client-server architecture, there are other solutions where the connection between clients does not flow through servers, but directly between clients that play the role of both client and server (these peer-to-peer networks). A popular protocol for real-time communication in such networks is WebRTC.

In the .NET environment for real-time communication, we can use the open-source SignalR library, which is part of the ASP.NET Core web framework, so it is easy to add it to existing projects as an additional level of middleware when processing incoming requests. The library simulates method calls on the client from the server side and method calls on the server from the client side (Remote Procedure Call - RPC), but does not guarantee the appropriateness of the no. parameters and their types. From the server, we can call methods on all clients, on a specific group of clients, or on just one client.

Schematic of how the SignalR library works (https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr)

Its main advantage is the simplicity of implementation thanks to the software development packages (SDK) for many different platforms, which hide the inner workings of the service from the programmers, and the possibility of easy hosting with the Azure SignalR service. An additional advantage is that the service itself chooses the most appropriate connection type (described above) between the client and the server.

The use of the library is based on special classes called hubs, which represent an abstraction of the connection between clients and the server. For them, we define methods that clients can call on the server.

The example below shows an example of a simple text conversation implementation. First, we define the base node for the conversation on the server. The methods of this class represent methods that can be called by clients on the server. When the SendMessage method is called, the client sends the user ID (userId) and the content of the message (message), while the server calls the ReceiveMessage method on all clients with the specified parameters.

Implementation of text conversation on the server in the .NET environment (own source)

The example below shows a JavaScript web client implementation using the official library (@microsoft/signalr). Clients connect to the node URL (/chat in the example below). A connection is represented by the connection object. The on method represents a listener to the method call, the name of which is given as the first parameter, and as the second the function that is executed on the event. We implement methods on the server through the invoke method of the connection object, which requires the name of the method as the first argument, followed by its parameters.

By default, data is transferred between the server and clients in JSON format, but the library also supports the more efficient MessagePack format.

Implementation of the web client in JavaScript language (own source)

Although the library greatly facilitates development, it has its drawbacks. One of the main ones is the scalability of the system for self-hosting and ensuring uninterrupted operation, since its implementation is very difficult to distribute on several separate servers. This turns out to be especially difficult if we want to reduce latency for remote users and host in several different locations, as the solution design is limited to just one. Also, the library does not ensure reliable delivery and order of messages, which can degrade the user experience.




What are others reading?