WebSocket - Comunicazione con il server

Il Web è stato in gran parte costruito attorno al paradigma di richiesta / risposta di HTTP. Un client carica una pagina web e quindi non accade nulla finché l'utente non fa clic sulla pagina successiva. Intorno al 2005, AJAX ha iniziato a rendere il web più dinamico. Tuttavia, tutta la comunicazione HTTP è gestita dal client, che richiede l'interazione dell'utente o il polling periodico per caricare nuovi dati dal server.

Le tecnologie che consentono al server di inviare i dati a un client nel momento stesso in cui sa che sono disponibili nuovi dati sono in circolazione da un po 'di tempo. Vanno con nomi come"Push" o “Comet”.

Con long polling, il client apre una connessione HTTP al server, che la mantiene aperta fino all'invio della risposta. Ogni volta che il server ha effettivamente nuovi dati, invia la risposta. Il polling lungo e le altre tecniche funzionano abbastanza bene. Tuttavia, tutti questi condividono un problema, portano il sovraccarico di HTTP, che non li rende adatti per applicazioni a bassa latenza. Ad esempio, un gioco sparatutto multiplayer nel browser o qualsiasi altro gioco online con un componente in tempo reale.

Portare i socket sul Web

La specifica Web Socket definisce un'API che stabilisce connessioni "socket" tra un browser Web e un server. In parole povere, esiste una connessione persistente tra il client e il server ed entrambe le parti possono iniziare a inviare dati in qualsiasi momento.

La connessione Web socket può essere aperta semplicemente utilizzando un costruttore -

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);

wsè il nuovo schema URL per le connessioni WebSocket. C'è anchewss, per una connessione WebSocket sicura allo stesso modo https viene utilizzato per connessioni HTTP protette.

Il collegamento immediato di alcuni gestori di eventi alla connessione consente di sapere quando la connessione viene aperta, ha ricevuto messaggi in arrivo o si è verificato un errore.

Il secondo argomento accetta facoltativo subprotocols. Può essere una stringa o un array di stringhe. Ogni stringa dovrebbe rappresentare un filesubprotocol nome e server accetta solo uno dei passati subprotocolsnella matrice. Accettatosubprotocol può essere determinato accedendo alla proprietà del protocollo dell'oggetto WebSocket.

// When the connection is open, send some data to the server
connection.onopen = function () {
   connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
   console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
   console.log('Server: ' + e.data);
};

Comunicare con il server

Non appena abbiamo una connessione al server (quando viene attivato l'evento open) possiamo iniziare a inviare dati al server utilizzando il metodo send (your message) sull'oggetto connessione. Un tempo supportava solo le stringhe, ma nelle ultime specifiche ora può inviare anche messaggi binari. Per inviare dati binari, viene utilizzato l'oggetto Blob o ArrayBuffer.

// Sending String
connection.send('your message');

// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);

for (var i = 0; i < img.data.length; i++) {
   binary[i] = img.data[i];
}

connection.send(binary.buffer);

// Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);

Allo stesso modo, il server potrebbe inviarci messaggi in qualsiasi momento. Ogni volta che ciò accade, viene attivato il callback onmessage. Il callback riceve un oggetto evento e il messaggio effettivo è accessibile tramite la dataproprietà.

WebSocket può anche ricevere messaggi binari nelle specifiche più recenti. I frame binari possono essere ricevuti in formato Blob o ArrayBuffer. Per specificare il formato del binario ricevuto, impostare la proprietà binaryType dell'oggetto WebSocket su "blob" o "arraybuffer". Il formato predefinito è "blob".

// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
   console.log(e.data.byteLength); // ArrayBuffer object if binary
};

Un'altra caratteristica aggiunta di recente di WebSocket sono le estensioni. Utilizzando estensioni, sarà possibile inviare frame compressi, multiplex, ecc.

// Determining accepted extensions
console.log(connection.extensions);

Comunicazione tra le origini

Essendo un protocollo moderno, la comunicazione cross-origin è integrata direttamente in WebSocket. WebSocket consente la comunicazione tra le parti su qualsiasi dominio. Il server decide se rendere disponibile il proprio servizio a tutti i client o solo a quelli che risiedono su un insieme di domini ben definiti.

Server proxy

Ogni nuova tecnologia presenta una nuova serie di problemi. Nel caso di WebSocket è la compatibilità con i server proxy, che mediano le connessioni HTTP nella maggior parte delle reti aziendali. Il protocollo WebSocket utilizza il sistema di aggiornamento HTTP (che viene normalmente utilizzato per HTTP / SSL) per "aggiornare" una connessione HTTP a una connessione WebSocket. Ad alcuni server proxy questo non piace e interromperà la connessione. Pertanto, anche se un determinato client utilizza il protocollo WebSocket, potrebbe non essere possibile stabilire una connessione. Questo rende la sezione successiva ancora più importante :)

Il lato server

L'utilizzo di WebSocket crea un modello di utilizzo completamente nuovo per le applicazioni lato server. Sebbene gli stack di server tradizionali come LAMP siano progettati attorno al ciclo di richiesta / risposta HTTP, spesso non gestiscono bene un gran numero di connessioni WebSocket aperte. Mantenere un gran numero di connessioni aperte allo stesso tempo richiede un'architettura che riceva un'elevata concorrenza a un basso costo delle prestazioni.