In un precedente articolo (https://www.aspitalia.com/articoli/asp.net-core/anteprima-aspnet-core-2-1-parte-2-p-2.aspx) abbiamo visto come usare ASP.NET Core SignalR per scambiare messaggi in tempo reale tra client e server.
Questa tecnologia, che sfrutta WebSockets per il trasporto dei dati, è ideale anche quando vogliamo monitorare da web lo stato di un sistema, come un macchinario industriale o un dispositivo IoT.
SignalR supporta lo scambio di messaggi sia testuali, come i parametri di funzionamento di una macchina, e sia binari, come le immagini catturate da una fotocamera.
In questo esempio vedremo appunto come usare ASP.NET Core SignalR per scambiare messaggi binari. Faremo in modo che l'applicazione, ad intervalli regolari, invii delle immagini ai client connessi. Il risultato che vogliamo ottenere è una pagina web che continui a visualizzare immagini, senza che debba essere ricaricata e senza inviare continue richieste ajax (polling).
Preparare il server
Iniziamo installando il seguente pacchetto NuGet che serve ad aggiungere il supporto a MessagePack.dotnet add package Microsoft.AspNetCore.SignalR.Protocols.MessagePack
MessagePack, documentato all'indirizzo https://msgpack.org/, è un formato di serializzazione dei dati che somiglia al JSON ma che, a differenza del JSON, è molto più compatto e supporta anche dati binari senza che debbano essere codificati in Base64.
Grazie al pacchetto che abbiamo installato, ASP.NET Core SignalR si arricchisce di un protocollo di comunicazione che sfrutta MessagePack per ottimizzare la quantità di dati trasferiti tra server e client.
Il prossimo passo consiste nel creare un hub di ASP.NET Core SignalR che useremo per inviare le immagini da server a client. Creiamo dunque un file di codice Hubs/ImageStreamHub.cs e inseriamo al suo interno questa classe.
public class ImageStreamHub : Hub<IImageStreamClient> { //Per questo esempio, qui non è necessario inserire nulla }
Come si vede, questo hub deriva dalla classe base Hub
public interface IImageStreamClient { Task ReceiveImage(byte[] image); }
Questa interfaccia definisce il metodo ReceiveImage che invocheremo lato server per inviare immagini al client. Come si nota, il suo paramento è di tipo byte[] che è idoneo per il contenuto binario di un'immagine.
Registrare i servizi di ASP.NET Core SignalR
A questo punto abbiamo preparato tutto il necessario e dobbiamo semplicemente registrare i servizi di ASP.NET Core SignalR. Quindi andiamo nel metodo ConfigureServices della classe Startup e aggiungiamo la seguente istruzione.//Mettiamo questa riga in un qualsiasi punto nel metodo ConfigureServices services.AddSignalR().AddMessagePackProtocol();
Come si vede, usando il metodo AddMessagePackProtocol abbiamo indicato di voler usare il protocollo di comunicazione basato su MessagePack.
Ora andiamo nel metodo Configure della classe Startup per usare il middleware di ASP.NET Core SignalR e indicare l'indirizzo a cui il client potrà collegarsi al nostro hub.
//Aggiungiamo questa riga prima di app.UseMvc app.UseSignalR((configure) => { configure.MapHub<ImageStreamHub>("/image-stream", options => { //Limite di peso dell'immagine da inviare al client options.ApplicationMaxBufferSize = 256 * 1024; //256KB }); });
In questo punto è anche importante valorizzare l'opzione ApplicationMaxBufferSize per indicare il peso massimo che un'immagine può assumere.
Inviare immagini al client
Gli hub di ASP.NET Core SignalR sono ben integrati con la dependency injection di ASP.NET Core e quindi, nei componenti della nostra applicazione, possiamo ricevere il servizio IHubContextpublic class ImageGenerator : BackgroundService { private readonly IHubContext<ImageStreamHub, IImageStreamClient> hubContext; //Riceviamo il servizio IHubContext<THub, T> nel costruttore public ImageGenerator(IHubContext<ImageStreamHub, IImageStreamClient> hubContext) { this.hubContext = hubContext; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //Questo hosted service invia ai client un'immagine ogni secondo //finché l'applicazione non viene arrestata while(!stoppingToken.IsCancellationRequested) { byte[] imageData = GetImageData(); //Possiamo inviare un messaggio ai client in maniera fortemente tipizzata //invocando il metodo ReceiveImage che avevamo definito nell'interfaccia await hubContext.Clients.All.ReceiveImage(imageData); //Attendiamo un secondo e poi il ciclo ricomincia await Task.Delay(1000, stoppingToken); } } private byte[] GetImageData() { //TODO: Qui logica per leggere il contenuto dell'immagine //ad esempio da una cartella in cui la webcam la salva } }
Per chiarimenti sugli hosted service, si veda un precedente script all'indirizzo https://www.aspitalia.com/script/1276/Operazioni-Background-Hosted-Service-ASP.NET-Core.aspx
Se usiamo un hosted service, ricordiamoci di registrarlo dal metodo ConfigureServices della classe Startup.
services.AddHostedService<ImageGenerator>();
Nel prossimo script...
Per ora abbiamo solo visto come preparare la parte server dell'applicazione ASP.NET Core. Nel prossimo script vedremo quale codice JavaScript usare nella parte client per ricevere e visualizzare le immagini inviate dal server.Il codice dell'applicazione dimostrativa è già pubblicato nel repository GitHub https://github.com/aspitalia/aspnetcore-signalr-binary
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Hosting di componenti WebAssembly in un'applicazione Blazor static
Usare un KeyedService di default in ASP.NET Core 8
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
Eseguire operazioni sui blob con Azure Storage Actions
Creazione di plugin per Tailwind CSS: espandere le Funzionalità del Framework
Generare velocemente pagine CRUD in Blazor con QuickGrid
Effettuare il binding di date in Blazor
Utilizzare Azure AI Studio per testare i modelli AI
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Rinnovare il token di una GitHub App durante l'esecuzione di un workflow
Eseguire una ricerca avanzata per recuperare le issue di GitHub
Inference di dati strutturati da testo con Semantic Kernel e ASP.NET Core Web API