Consumare dati binari in realtime lato client con ASP.NET Core SignalR

di , in ASP.NET Core,

Nello script precedente (https://www.aspitalia.com/script/1327/Dati-Binari-Realtime-ASP.NET-Core-SignalR.aspx) abbiamo implementato la parte server di un'applicazione web che, grazie ad ASP.NET Core SignalR, invia immagini in tempo reale ai client connessi. Questo esempio è utile se dobbiamo monitorare le immagini catturate da una webcam oppure ricevere altro tipo di dati binari (o anche testuali) da dispositivi industriali o IoT.

Preparare il client

Ora continuiamo sviluppando la parte client, in cui andremo a ricevere i dati binari dal server e a visualizzarli in una pagina HTML. Per prima cosa aggiungiamo i riferimenti ai file JavaScript necessari.

  • Il client di ASP.NET Core SignalR (pacchetto npm @aspnet/signalr), che espone le funzionalità basilari per stabilire una connessione bidirezionale con il server;
  • L'implementazione del protocollo MessagePack (pacchetto npm msgpack5) che contiene la logica di serializzazione dei messaggi in formato binario;
  • Il supporto a MessagePack per SignalR (pacchetto npm @aspnet/signalr-protocol-msgpack).

Queste dipendenze client possiamo procurarcele in vari modi: usando libman (https://www.aspitalia.com/script/1304/Usare-LibMan-Gestire-Dipendenze-Client-ASP.NET-Core.aspx), npm, oppure semplicemente referenziando i file da un CDN come jsdelivr, proprio come mostrato in questo esempio. Possiamo aggiungere questo codice dove preferiamo nel corpo della pagina HTML o ad esempio nella @section Scripts di una view Razor.

Ora che abbiamo referenziato i file necessari, aggiungiamo di seguito il JavaScript per configurare la connessione all'hub di ASP.NET Core SignalR.

<script>
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/image-stream") //Url del nostro hub SignalR (spiegato nel precedente articolo)
    .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) //Usiamo il protocollo binario basato su MessagePack
    .build();
</script>

Ora dobbiamo registrarci per ricevere i messaggi 'ReceiveImage' inviati dal server. Nel farlo, indichiamo una funzione di callback che verrà automaticamente invocata ogni volta che il server invia una nuova immagine da visualizzare. La callback riceve i dati binari in forma di Uint8Array (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), un oggetto JavaScript che rappresenta un array di byte.

Ottenuto l'array di byte potremmo certamente leggerne il contenuto come un comune array. Nel nostro caso, dato che abbiamo a che fare con delle immagini, si pone il problema di come visualizzarle nella pagina web. A tale scopo dobbiamo incapsulare l'array di byte in un oggetto Blob (https://developer.mozilla.org/en-US/docs/Web/API/Blob) da cui potremo ottenere un percorso assegnabile alla proprietà src di un elemento img.

<script>
let previousObjectURL;
connection.on('ReceiveImage', data => {
    //La variabile data è di tipo Uint8Array
    //Creo un blob a partire dai dati binari che ho ricevuto
    const blob = new Blob([data], {type: "image/png"});
    
    //Creo un percorso al Blob e lo assegno alla proprietà src di un elemento img
    const currentObjectURL = URL.createObjectURL(blob);
    document.getElementById('targetImage').src = currentObjectURL;

    //Dealloco l'URL generato precedentemente, così da evitare dei memory leak.
    if (previousObjectURL) {
        URL.revokeObjectURL(previousObjectURL);
    }

    //Conservo il riferimento all'URL che ho generato poco fa, così che lo si possa deallocare poi
    previousObjectURL = currentObjectURL;
});
</script>

Ora siamo pronti per stabilire una connessione all'hub di ASP.NET Core SignalR. A quel punto cominceremo a ricevere le immagini dal server.

<script>
connection.start();
</script>

Non dimentichiamo di aggiungere alla pagina l'elemento img che visualizzerà le immagini. Il suo attributo src può essere inizializzato con un'immagine qualsiasi, perché poi verrà riassegnato con i percorsi ai Blob creati di volta in volta.

<img id="targetImage" src="/blank.gif" width="200" height="200">

Provare il funzionamento

Se avviamo l'applicazione, vedremo una nuova immagine apparire ogni secondo. Andando a curiosare nella scheda "Network" o "Rete" degli strumenti di sviluppo del browser (tasto F12), vedremo apparire tante richieste, una per ogni immagine mostrata. Come si vede qui, il browser crea i percorsi ai Blob con un formato particolare, contenente un codice che lo aiuta a identificare univocamente la risorsa binaria presente in memoria.


Inoltre, se usiamo un web debugger come Fiddler, vedremo che i dati binari sono traferiti tali e quali, senza alcuna codifica Base64, dato che MessagePack è appunto un protocollo che supporta il trasferimento binario.

Conclusioni

Grazie ad ASP.NET Core SignalR e al trasporto MessagePack, abbiamo visto come trasferire dati binari da server a client in tempo reale. Lo stesso protocollo può essere usato anche per inviare dati testuali.
Il codice presentato in questo script si trova su GitHub, nel seguente repository.
https://github.com/aspitalia/aspnetcore-signalr-binary
Nel ramo start-stop dello stesso repository si trova anche un'implementazione minimale della funzionalità di avvio e arresto che consente ai client di decidere quando ricevere i contenuti binari dal server. In questo modo, l'invio è ottimizzato perché avviene solo quando ci sono client connessi.

Commenti

Visualizza/aggiungi commenti

Consumare dati binari in realtime lato client con ASP.NET Core SignalR (#1328)
| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi