Con WebSocket, si identifica una tecnologia che consente di creare una connessione persistente tra client e server tramite cui scambiarsi dati in maniera efficiente.
Limiti dei Server-Sent Events
I Server-Sent Events consentono di avere informazioni dal server quando queste sono effettivamente disponibili, evitando di dover ricorrere a meccanismi di polling o altre soluzioni che possono rappresentare un inutile spreco di risorse come la CPU e la banda.
Pur rappresentando un'ottima soluzione nella maggior parte dei casi, i Server-Sent Events hanno alcune limitazioni che non li rendono idonei per l'utilizzo in determinati contesti.
In particolare, essi non implementano una comunicazione bidirezionale, cioè i Server-Sent Events mettono a disposizione un canale con cui il server comunica con il client, ma non consentono al client di inviare informazioni verso il server. Inoltre, essi si fondano sempre sul protocollo HTTP che non è proprio adatto in contesti in cui è necessaria una comunicazione bidirezionale efficiente, come ad esempio in un gioco online o una chat in cui interagiscono più utenti e la comunicazione in tempo reale deve essere la più efficiente possibile.
Le WebSocket API
Dal punto di vista di JavaScript, le API per utilizzare WebSocket non sono molto diverse da quelle per utilizzare i Server-Sent Events. Anche in questo caso abbiamo un costruttore specifico che ci consente di creare un oggetto tramite cui gestire la comunicazione client-server:
var ws = new WebSocket("ws://www.html.it/myServerPage");
L'URL della pagina che passiamo al costruttore indica il protocollo ws:. Infatti, requisito fondamentale per poter utilizzare i WebSocket è che il server supporti questo protocollo. Esiste anche la versione sicura di WebSocket che prevede il prefisso wss:.
Una volta creato l'oggetto WebSocket possiamo gestire gli eventi di apertura della connessione, di ricezione di un messaggio dal server, di intercettazione di un errore di comunicazione e di chiusura della connessione come mostrato di seguito:
ws.addEventListener("open", function() {
console.log("Figura X. stata aperta una connessione");
});
ws.addEventListener("message", function(e) {
console.log("Il server ha inviato il messaggio: " + e.data);
});
ws.addEventListener("error", function(error) {
console.log("Si è verificato il seguente errore: " + error);
});
ws.addEventListener("close", function() {
console.log("Figura X. stata chiusa la connessione");
});
Send, inviare dati al server
Come possiamo vedere, fin qui le API per gestire i WebSocket sono del tutto identiche a quelle per gestire i Server-Sent Events. I WebSocket però prevedono la possibilità di inviare dati al server tramite il metodo send():
ws.send("messaggio dal client");
L'invio di messaggi al server non è limitato a semplici stringhe. È possibile inviare dati binari codificati, ad esempio, in un ArrayBuffer
. Il seguente esempio mostra come inviare un'immagine al server:
var myCanvas = document.getElementById("myCanvas");
var context = myCanvas.getContext("2d");
var img = context.getImageData(0, 0, 400, 320);
var binaryData = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binaryData[i] = img.data[i];
}
ws.send(binaryData.buffer);
Anche in ricezione possiamo ricevere dati binari. In questo caso è opportuno impostare il tipo di dati binari per interpretare correttamente i dati ricevuti. Ad esempio, nel seguente codice viene indicato che i dati ricevuti devono essere interpretati come ArrayBuffer:
ws.binaryType = "arraybuffer";
ws.addEventListener("message", function(e) {
console.log("Sono stati ricevuti " + e.data.byteLength + " byte");
});
Infine, possiamo chiudere una connessione WebSocket tramite il metodo close():
ws.close();
Supporto e librerie server-side
Come abbiamo accennato, dal punto di vista di JavaScript non ci sono grosse differenze nella gestione dei WebSocket
. L'API prevista per interagire con questo protocollo è abbastanza simile a quella prevista per i Server-Sent Events
.
Tuttavia lato server il supporto dei WebSocket varia in base alla specifica piattaforma. Sono ad esempio disponibili librerie come SuperWebSocket e Fleck per ASP.NET, o PHP-Websocket e Ratchet per PHP, Java WebSocket per Java o WebSocket-Node per Node.js, per citarne qualcuna.
Uno dei problemi principali dell'adozione dei WebSocket è da un lato il mancato supporto dei browser più datati, dall'altro il potenziale blocco di questo protocollo da parte di proxy non adeguatamente configurati.
Per aggirare il problema è opportuno utilizzare librerie che supportano i WebSocket
ma allo stesso tempo forniscono un meccanismo di callback che possa consentire l'utilizzo di tecnologie alternative, come ad esempio Comet, anche se meno performanti. Esempi di tali librerie sono SignalR per l'ambiente ASP.NET e socket.io per Node.js.