Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Introduzione ai WebSocket

I dettagli del protocollo e delle API del protocollo per le real time applications.
I dettagli del protocollo e delle API del protocollo per le real time applications.
Link copiato negli appunti

Questo articolo è la traduzione di "WebSockets: A Guide", di Jack Lawson e pubblicato su buildnewgames.com. Con l'approvazione di Microsoft.

I WebSockets forniscono una comunicazione bidirezionale in tempo reale tra client e server, e quindi sono estremamente utili nella costruzione dei moderni web games. I giochi browser-based possono sfruttare connessioni a bassa latenza e always-on, per la trasmissione rapida di informazioni sullo stato dei giocatori e del gioco intero in un modo precedentemente solo emulato da metodi come polling Ajax e Comet. È utile considerare in primis la storia di WebSockets e comprendere come funziona a livello tecnico, prima di esaminare come possiamo usare WebSockets in modo più efficace. Armati di questa conoscenza, possiamo semplificare il livello di rete e creare giochi incredibilmente reattivi che forniscono un elevato livello di interazioni multiplayer.

Storia

Internet è stata sviluppata (per semplificare grossolanamente) come un modo per consentire alle organizzazioni di condividere informazioni in modo efficiente e senza ritardi. L'informazione su Internet viene trasportata attraverso una suite di protocolli di connessione chiamato TCP/IP, che definisce il metodo il quale fare condividere le informazioni tra computer in una rete decentralizzata con una ragionevole certezza sul loro arrivo a destinazione.

TCP/IP correla il messaggio di informazioni, come l'origine e la destinazione. Il messaggio contiene un checksum (un valore calcolato a partire dai dati stessi) che può essere utilizzato dal ricevente per verificare se tutte le informazioni siano state ricevute correttamente.

La diffusione della "rete" come sappiamo è passata attraverso il protocollo HTTP, che fornisce un livello di astrazione che impacchetta le connessioni TCP/IP in un involucro contenente informazioni relative alla richiesta, nonché i dati per la richiesta stessa, come ad esempio i campi dei form e i valori dei cookie. Questo strato HTTP fornisce una semplice interfaccia di richiesta e risposta che funziona bene per azioni come ottenere una pagina web, caricamre un'immagine, o passare dati a un server per la persistenza.

Nell'evoluzione che ha avuto lo sviluppo di applicazioni web dal 2004 in poi, Ajax è diventato un metodo estremamente utile attraverso il quale recuperare i dati da un server. Ajax è un'interfaccia attraverso la quale javascript può creare una richiesta HTTP e gestire la risposta in modo asincrono con una funzione di callback in caso di successo o il fallimento.

Laddove gli utenti precedentemente dovevano aggiornare o cambiare pagina per visualizzare il contenuto aggiornato, con poco codice JavaScript si può effettuare la richesta al server, ottenere dati aggiornati, e visualizzare i dati nella pagina, per applicazioni che rispondano senza più soluzione di continuità. Gmail, Facebook e Twitter sono tutti esempi considerevoli di di "single-page-apps", che prelevano i dati tramite chiamate al server che avvegono dietro le quinte, permettendo all'utente un flusso di lavoro più agevole. HTTP è rimasto invariato dal 1999, supportando la trasmissione di questi pacchetti attraverso connessioni usa e getta.

Seguendo l'evoluzione delle applicazioni web, è cresciuta anche la necessità di una comunicazione in tempo reale. Le applicazioni di chat, i giochi online e i sistemi di notifica si basano su un abuso del protocollo HTTP attraverso sistemi come polling Ajax, connessioni persistenti HTTP Comet, aprendo iframe per effettuare il polling di nuovi dati dal server o utilizzando Flash per il livello di rete o per costruire tutta l'applicazione. Anche se evoluti, questi metodi avevano aspetti negativi come inefficienze o complessità. Eppure la risposta era proprio sotto il naso del protocollo HTTP: la stessa connessione TCP che sottende l'HTTP poteva essere utilissata per collegamenti a doppio senso, persistenti ed efficienti, direttamente tra client (browser) e server web.

La specifica WebSocket è stata completata in un momento fantastico nell'era dello sviluppo di applicazioni web: insieme all'avvento di HTML5 e di una pletora di tecnologie ad esso correlate per l'open web. Ora è una specifica stabile e supportato da browser moderni come Chrome, Firefox e Internet Explorer 10.

La connessione continua TCP consente agli sviluppatori di realizzare giochi online molto reattivi e connessi in modo molto più efficiente, sia per l'utilizzo delle risorse di client e server sia in fase di sviluppo, utilizzando un flusso "nativo" invece di un sistema di interrogazione a polling.

Con i WebSocket, se un utente muove il proprio personaggio del gioco, in pochi millisecondi un altro utente vedrà muoversi il personaggio sul proprio schermo. Inoltre un giocatore può chattare sapendo che i suoi messaggi appaiono istantaneamente nel gioco, un carro armato può sparare un colpo, e il vettore può essere tracciato in tempo reale su due schermi contemporaneamente. Tutto questo può essere costruito con tecnologie open web.

Un WebSocket visti da vicino

Parleremo del modello RFC6455 (hybi-17), che ha alcune differenze rispetto a implementazioni precedenti. Poiché questo è lo standard ufficiale, non staremo a discutere le differenze.

Tecnicamente parlando, un WebSocket è una connessione TCP persistente, bi-direzionale full-duplex, garantita da un sistema di handshaking client-key ed un modello di sicurezza origin-based. Il sistema inotre maschera le trasmissioni dati per evitare lo sniffing di pacchetti di testo in chiaro.

Vediamo cosa significa questa definizione punto per punto:

Caratteristica Descrizione
Bi-directional il client è connesso al server, e il server è connesso al client. Ciascuno può ricevere eventi come collegato e scollegato e possono inviare dati all'altro.
Full duplex il server e il client può inviare dati nello stesso momento senza collisioni.
TCP Protocollo sottostante tutte le comunicazioni Internet, che fornisce un meccanismo affidabile per trasportare un flusso di byte da un'applicazione all'altra.
Client-key handshake il client invia al server una chiave segreta di 16 byte con codifica base64. Il server poi aggiunge una stringa (anche detta "magic string" e specificata nel protocollo come "258EAFA5-E914-47DA-95CA-C5AB0DC85B11") e rimanda il risultato, elaborato con SHA1, al client. In questo modo, il client può essere certo che il server cui aveva inviato la sua chiave è lo stesso che apre la connessione.
Sicurezza origin-based L'origine della richiesta WebSocket viene verificata dal server per determinare che provenga da un dominio autorizzato. Il server può rifiutare le connessioni socket da domini non attendibili.
Trasmissione dati mascherata Il cliente inva una chiave di 4 byte per l'offuscamento nella trama iniziale di ogni messaggio. Essa è utilizzata per effettuare uno XOR bit a bit tra dati e chiave. Ciò aiuta a prevenire lo sniffing di dati This helps to prevent data sniffing, poiché un malintenzionato dovrebbe essere capace di determinare il byte di inizio del messaggio per poterlo decrittare.

L'RFC definisce un frame WebSocket come segue:

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+

Il frame dati è abbastanza semplice: contiene informazioni sullo stao di un particolare frame, la lunghezza del contenuto, la masking-key e i dati veri e propri.

Iniziano dall'alto e da sinistra verso destra abbiamo:

Bit Descrizione
Fin (bit 0) serve ad indicare l'ultimo frame del messaggio, sarà quindi impostato a 1 quando il frame è l'ultimo di una serie, oppure se il messaggio è composto da un singolo frame (in quanto primo e ultimo della serie)
RSV1, RSV2, RSV3 (bits 1-3) questi tre bit sono riservati alle estensioni dei websoket e dovrebbero essere 0 a meno che ne sia richiesto l'uso da parte di una specifica estensione
Opcode (bits 4-7) questi quattro bit determinano la tipologia di frame. I frame di controllo comunicano lo stato del WebSoket, mentre gli altri trasportano dati. Le diverse tipologie ti codici includono:

  • 0x0 - continuation frame, contiene dati che devono essere messi in coda al frame precedente
  • 0x1 - text frame, questo frame, ed eventuali successivi, contiene del testo
  • 0x2 - binary frame, questo frame, ed eventuali successivi, contiene dati in formato binario
  • 0x3 - x7 - riservati a frame che non siano di controllo, per essere sfruttati da estensioni di websocket
  • 0x8 - close frame, questo frame dovrebbe chiudere la connessione
  • 0x9 - ping frame
  • 0xA - pong frame
  • 0xB - 0xF - riservati a frame di controllo
Mask (bit 8) determina se un certo frame usi una maschera o no
Lunghezza del Payload (bits 9-15, o 16-31, o 16-79) questi sette bit indicano la lunghezza del contenuto: se il valore in questo set è 126, la lunghezza viene rappresentata dai seguenti 2Bytes (bit 16-31), se invece è 127, la rappresentazione viene estesa fino al bit 79 (4byte in più)
Masking Key (i seguenti 4 Byte) Rappresenta la maschera, quando il bit Mask è impostato a 1
Payload (tutti i dati successivi) finalmente i dati. È possibile trasferire il payload con più frame: conosciamo la lunghezza effettiva del messaggio grazie all'informazione sulla lunghezza che abbiamo codificato nell'header del frame e possiamo aggiungere dati finché non riceviamo un frame con il flag Fin. Tutti i frame consecutivi saranno contrassegnati dall'opcode 0x0 (continuation frame).

Il frame dei dati nella RFC6455 ci permette di capire quanto sia grande un messaggi, il tipo di codifica e l'eventuale maschera. Possiamo inviare messaggi di qualunque lunghezza, purché questa lunghezza sia rappresentabile con un numero base-64 (cioè 9.223.372.036.854.775.808 cifre).

La WebSocket API

La WebSocket API con la quale avremo a che fare in JavaScript risulta semplice ed elegante e definisce un oggetto che contiene:

  • Informazioni sullo stato della connessione (connecting, open, closing e closed)
  • Metodi per interagire con la connessione WebSocket (chiudere una connessione e inviare dati)
  • Eventi che vengono sollevati all'occorrenza di un evento WebSocket (quando un socket viene aperto, chiuso o riceve in risposta un messaggio di errore)

Una semplice implemetazione di una connessione WebSocket potrebbe essere questa:

var onOpen = function() {
console.log("Socket opened.");
socket.send("Hi, Server!");
},
onClose = function() {
console.log("Socket closed.");
},
onMessage = function(data) {
console.log("We get signal:");
console.log(data);
},
onError = function() {
console.log("We got an error.");
},
socket = new WebSocket("ws://echo.websocket.org/");
socket.onopen = onOpen;
socket.onclose = onClose;
socket.onerror = onError;
socket.onmessage = onMessage;

Una volta chiamato il costruttore del WebSocket, browser e server iniziano l'handshaking. Inizialmente la connessione è effettuata utilizzando un comando HTTP "Upgrade", l'echo test tool mostra le seguenti informazioni nel tab "network" degli strumenti per sviluppatori di Chrome:

Questo header è ricco di informazioni interessanti:

  1. Header della richiesta
    1. Connection: il comando "Upgrade" inviato indica al server che stiamo tentando di passare ad una connessione WebSocket.
    2. Origin: questa origine è verificata dal server per capire se i messaggi provengono da una fonte autorizzata dai suoi protocolli di sicurezza.
    3. Sec-WebSocket-Key: questa chiave compone la prima parte dell'handshake. È generata in modo casuale e codificata come stringa base64 di 16-byte. Sec-WebSocket-Version: permette al server di rispondere con il protocollo con la versione più adeguata del protocollo.
  2. Header della risposta
    1. Sec-WebSocket-Accept: il server aggiunge la stringa specificata dal protocollo "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" alla chiave di sicurezza inviata dal cliente e sottopone il risultato all'hashign sha-1. Il client potrà verificare il risultato di questo hash per determinare se la chiave, e quindi il server, corrisponde.

Supponendo che tutto vada bene, il nostro oggetto socket avrebbe un readyState impostato a 1, che corrisponde a open. Possiamo inviare messaggi da questo stato e utilizzare onMessage per gestire la ricezione di dati dal server. I possibili stati per readyState sono 0 (in connessione), 1 (canale aperto), 2 (in chiusura), e 3 (canale chiuso).

Pratiche di implementazione

Quando si lavora con Ajax, la maggior parte delle volte si usano funzioni di callback per gestire le risposte del server. Le richieste Ajax (considerando che Ajax è semplicemente un metodo per effettuare una chiamata HTTP) inviano una richiesta e ricevono una risposta, che a sua volta chiama uno specifico metodo di callback. Tali richieste sono spesso create come un sistema di polling che effettua un ping al server a intervalli di pochi secondi per ottenere nuovi dati. Un esempio potrebbe essere quello di un gioco con una chat.

Al server viene inviata una richiesta Ajax ogni 5 secondi, per verificare la presenza di nuovi messaggi nella chat. Se c'è un nuovo messaggio, mostralo. Altrimenti non fare nulla. Controlla di nuovo tra cinque secondi.

Tuttavia, questa architettura non si adatta bene ai casi in cui si ha a che fare con delle chiamate veramente asincrone. Si può ricevere qualsiasi dato in qualsiasi momento al quale rispondere seguendo qualche logica, la differenza chiave è che non si può fare affidamento su questi dati come risposta ad una chiamata che abbiamo fatto in precedenza. Una architettura callback-based accoppia in maniera stretta il nostro livello di rete con il nostro livello client, ed è possibile fare assunzioni sulle condizioni del servizio e sulla disponibilità del server. In questo modo, si può cadere nella trappola di consentire al nostro livello di rete di determinare il flusso di controllo della nostra applicazione.

Vediamo un semplice esempio di un sistema di chat di un gioco che segue la logica di callback. Un giocatore ad un terminale del sistema invia un messaggio, il messaggio viene instradato attraverso il server, e un altro giocatore riceve i dati in formato JSON con quel messaggio di chat. Questo messaggio può assumere diverse forme, potrebbe essere un normale messaggio, un messaggio privato, o un annuncio di sistema. Un approccio tradizionale tende ad includere del codice come quello che segue:

var onMessage = function(data) {
data = JSON.parse(data);
if (data.type == 0) {
displayNormalMessage(data.message);
} else if (data.type == 1) {
displayPrivateMessage(data.message);
} else if (data.type == 2) {
displaySystemAnnouncement(data.message);
}
};

Questo tipo di sistema può crescere rapidamente in modo incontrollato, aggiungendo nuovi tipi di messaggi di chat, ad esempio, la lista cresce diventando sempre più lunga. L'aggiunta di caratteristiche, come gli alert se il proprio nome viene menzionato, aggiunge complessità al sistema. Una volta che si iniziano ad aggiungere delle azioni sullo stesso socket di connessione, bisogna iniziare ad aggiungere controlli condizionali per verificare se il tipo di dati è "colpo sparato", o “giocatore mosso”, o “giocatore si inserisce nel gioco” e così via. Questa lista può allungarsi in un elenco di funzioni e tipi corrispondenti sempre crescente.

var onMessage = function(data) {
data = JSON.parse(data);
if (data.type == 0) {
// type 0: message
if (data.messageType == 0) {
// msg type 0: normal
displayNormalMessage(data.message);
} else if (data.messageType == 1) {
// msg type 1: private
displayPrivateMessage(data.message);
} else if (data.messageType == 2) {
// msg type 2: announcement
displaySystemAnnouncement(data.message);
}
} else if (data.type == 1) {
// type 1: move
movePlayer(data.player, data.direction);
} else if (data.type == 2) {
// type2 : attack
}
// etc
};

Al contrario, una struttura più robusta che utilizza il sistema di gestione AmplifyJS publish-subscribe (d'ora in poi indicato come pub/sub) potrebbe essere simile alla seguente:

var socket = new WebSocket("ws://echo.websocket.org/"),
pubsub = amplify;
socket.onopen = function() {
pubsub.publish("chat/open")
};
socket.onclose = function() {
pubsub.publish("chat/close")
};
socket.onerror = function() {
pubsub.publish("chat/error")
};
socket.onmessage = function(data) {
pubsub.publish("chat/message/receive", data)
};
pubsub.subscribe("chat/message/send", function(data) {
socket.send(data);
});
pubsub.subscribe("chat/message/receive", function(data){
console.log(data);
});
pubsub.subscribe("chat/open", function() {
console.log("Socket opened.");
pubsub.publish("chat/message/send", "Hi, server!");
});

Mentre l'implementazione di questa semplice funzionalità potrebbe sembrare un po' gonfiata a prima vista, è possibile dimostrare che così si aumenta di gran lunga la manutenibilità e la flessibilità. Spostando la gestione del WebSocket fuori dal callback, si può includere qualsiasi numero di script esterni e moduli che possono inviare o ricevere dati senza la necessità di conoscere i dettagli della connessione e senza introdurre alcuna logica aggiuntiva e controlli condizionali nel codice di gestione WebSocket.

La connessione WebSocket è di per sé un altro modulo (un modulo per la gestione del traffico di rete), che ascolta le chiamate pub/sub e può eseguire azioni verso un server. Con un po' di fantasia, si può anche estendere il livello di rete con localStorage e un modulo di intelligenza artificiale per il gioco offline in modalità singleplayer! Si può astrarre il livello di comunicazione di rete e fornire un metodo per aggiornare i dati a prescindere da come il livello di rete si presenta; lo strato può essere composto da WebSockets, Ajax, o anche un intero lato client aggiornato senza connessione. Inoltre, organizzando il codice in moduli, il codice guadagna testabilità e manutenibilità limitando le verifiche ai singoli moduli.

Abbiamo ancora bisogno di una sorta di mappatura che possiamo semplificare utilizzando un dizionario di definizioni dei tipi che determineranno il canale della chiamata. Un esempio può essere ["chat", "message", "normal"], mappato in modo sequenziale. Il nostro robusto strato pub-sub WebSocket potrebbe essere qualcosa di questo tipo:

var socket = new WebSocket("ws://echo.websocket.org/"),
pubsub = amplify,
player = { name: "George Lucas" };
socket.onopen = function() {
pubsub.publish("chat/open")
};
socket.onclose = function() {
pubsub.publish("chat/close")
};
socket.onerror = function() {
pubsub.publish("chat/error")
};
socket.onmessage = function(data) {
pubsub.publish(data.Type + "/" + data.SubType, data);
};
pubsub.subscribe("chat/message/send", function(data) {
socket.send(data);
});
pubsub.subscribe("chat/message/receive", function(data){
console.log(data);
});
pubsub.subscribe("chat/open", function() {
console.log("Socket opened.");
pubsub.publish("chat/message/send", "Hi, server!");
});
pubsub.subscribe("chat/message/normal", function(data){
console.log(data.From +":" + data.Message);
});
pubsub.subscribe("chat/message/normal", function(data){
if(data.From == player.Name){
console.log("You were mentioned in a message!");
}
});

Questo aggiornamento riduce il nostro intero sistema ad una singola riga di codice, basata sul tipo di dati che si stanno ricevendo; data.Type può essere qualcosa come "message" o "player" e data.SubType può essere "normal" o "move". Per maggior robustezza, si può invece passare Type come un array, che permette di sottoscrivere un qualsiasi tipo di dati. Chat può restare in ascolto in un canale "message" di base, mentre i messaggi di avviso privati possono essere ascoltati in un canale "message:private".

function(data){ pubsub.publish(data.Type.join(":"), data); };

Dal punto di vista della sottoscrizione, ora possiamo cominciare a vedere degli effetti interessanti. Ad esempio, se si usa un sistema Pub/Sub che permette di utilizzare predicati come Mediator.js, si possono utilizzare metodi di sottoscrizione più avanzati che fanno partire questo metodo solo se una funzione specifica, che agisce su dei dati, restituisce true. Il seguente esempio riguarda una sottoscrizione che avvisa il giocatore che il proprio nome è stato mensionato se la funzione predicato che viene passata restituisce true.

var socket = new WebSocket("ws://echo.websocket.org/"),
pubsub = new Mediator();
socket.onopen = function() {
pubsub.Publish("chat/open")
};
socket.onclose = function() {
pubsub.Publish("chat/close")
};
socket.onerror = function() {
pubsub.Publish("chat/error")
};
socket.onmessage = function(data) {
pubsub.Publish(data.Type.join(":"), data);
};
pubsub.Subscribe("chat:message:send", function(data) {
socket.send(data);
});
pubsub.Subscribe("chat:message:receive", function(data){
console.log(data);
});
pubsub.Subscribe("chat:open", function() {
console.log("Socket opened.");
pubsub.publish("chat:message:send", "Hi, server!");
});
pubsub.Subscribe("chat", function(data){
alertPlayerForChatMessage(data.message);
}, function(data){
return data.name == player.name;
});
pubsub.Subscribe("game:environment:status", function(data){
console.log("It has started to " + data.weatherType);
});

Con questa architettura, si può avere un modulo chat, un modulo di gioco, un modulo di ingresso, un modulo giocatore, un modulo lista di amici, e moduli per qualsiasi altra funzionalità di gioco. Tutte le parti del gioco possono essere costruite separatamente, con la capacità comune di comunicare attraverso un'interfaccia astratta. Il codice ha la massima flessibilità di aggiungere e rimuovere funzionalità a volontà, e lo sviluppatore può modificare e aggiungere codice specifico per la funzione alla quale sta lavorando.

Lo sviluppatore guadagna anche la possibilità di scrivere facilmente codice di tipo test-driven, attraverso framework come Jasmine or Sinon, senza la necessità di utilizzare oggetti mock per la connessione al WebSocket e senza problemi nei test.

Limitazioni

I WebSockets non rappresentano la soluzione a tutto. L'HTTP riveste ancora un ruolo chiave nella comunicazione tra client e server come via per inviare e chiudere connessioni per trasferimenti di dati di tipo one-time, come i caricamenti iniziali. Le richieste HTTP sono in grado di eseguire questo tipo di operazioni in modo più efficiente del WebSockets, chiudendo le connessioni una volta completate piuttosto che mantenendo lo stato della connessione.

Inoltre, i WebSockets possono essere utilizzati solo se gli utenti utilizzano i moderni browser con JavaScript abilitato. Mentre Flash è utile per fornire funzionalità di browser non compatibili, alcuni utenti potrebbero non essere in grado di accedere a contenuti di tipo javascript-only o Flash-only. Se possibile, dovrebbe essere previsto un metodo alternativo per accedre all'aplicazione attraverso un progressive enhancement.

Dovrebbero poi essere considerati possibili impatti sull'architettura di rete. WebSockets, essendo una connessione persistente, potrebbe richiedere molte più risorse rispetto ad un server Web standard. L'impatto sul bilanciamento del carico e sul firewall può essere mitigato, la specifica WebSocket permette di trasferire le connessioni. Un client può connettersi a un LoadBalancer che passa la connessione ad un application server per gestire l'elaborazione dei data frame.

WebSocket Server

La maggior parte dei linguaggi più popolari forniscono una implementazione per WebSocket. Quella che segue è un una lista di alcune delle librerie tra le più attive di recente per una selezione ristretta di linguaggi.

  1. Node
    1. Socket.io (supporta anche fallback per client che non supportano WebSocket)
    2. WebSocket-node (hybi-8, 13)
  2. C#
    1. Alchemy Websockets (hybi-00, 10, 13, 17, RFC 6455)
    2. Fleck (hybi-00, 10, 13, 17, RFC 6455)
  3. Java
    1. Java-WebSocket (hixie-75, hybi-00, 10, 17, RFC 6455)
    2. jWebSocket
  4. Python
    1. ws4py
  5. Erlang
    1. Misultin
  6. Ruby
    1. em-websocket (hixie-75, hybi-00, 5, 7, 13, 17)

Supporto per i Browser

I WebSocket sono supportati dalla maggior parte dei principali browser, anche se alcuni di essi hanno aggiunto il supporto solo in versioni alfa o beta più recenti. Su Wikipedia c'è un elenco aggiornato dei browser.

  1. Desktop
    1. Internet Explorer: la versione 10 supporta hybi-10
    2. FireFox: la 11 supporta RFC6455
    3. Chrome: la 16 supporta RFC6455
    4. Safari: la versione 5.0.1 supporta hybi-00
    5. Opera: la versione 11.00 supporta hybi-00 (deve essere abilitata dall'utente)
  2. Mobile
    1. Android browser: nessun supporto; ma Chrome per Android ha l'RFC6455
    2. iOS 5 browser: supporta hixie-75
    3. Opera Mobile: hybi-00 abilitato da impostazioni di sistema

Un supporto addizionale ai WebSocket può essere offerto, per i browser che non lo prevedono, da applicazioni Flash come web-socket-js. È possibile testare il supporto dei WebSocket da parte del vostro browser qui.

Client-side Event Management

Le callback possono portare ad un flusso di dati confuso: utilizzare un sistema di eventi custom o un sistema di pubblicazione/abbonamento con messaggi WebSocket può rendere tutto più chiaro e modulare.

Ecco alcune librerie che utili per implementare il pattern "pub/sub":

  1. AmplifyJS: gestisce pub/sub
  2. Backbone: include eventi custom (leggere questo articolo
    sull'uso di Backbone con i WebSocket)
  3. YUI:
    eventi custom
  4. Dojo:
    gestione pub/sub
  5. Mediator.js: classi per gestire pub/sub utilizzando sia Ajax sia WebSocket

Addy Osmani ha scritto un eccellente articolo sul pattern pub/sub che spiega come e quando sia più opportuno implementarlo.

Altro progetto assolutamente da non dimenticare è ASP.NET SignalR, ottimo se stiamo costruendo applicazioni realtime basate su .NET


Ti consigliamo anche