Una delle funzionalità più interessanti di HTML5 è WebSockets. I WebSocket ci consentono di comunicare con un server, senza la necessità delle tradizionali richieste AJAX.
In questo tutorial, impareremo molto sui WebSocket. Costruiremo un esempio pratico di client e server che comunicano tramite WebSocket. In questo tutorial useremo Node.js per il server. Se desideri utilizzare WebSockets con PHP, dai un’occhiata al nostro post di accompagnamento.
Cosa sono i WebSocket?
WebSockets è una tecnica per comunicazione bidirezionale su un socket (TCP), un tipo di tecnologia push.
Perché abbiamo bisogno di WebSocket?
I WebSocket sono ampiamente utilizzati quando un’applicazione non favorisce lunghi sondaggi. Con il polling lungo, il server invia costantemente risposte che possono contenere o meno i dati richiesti. Questi dati sono necessari per mantenere la connessione fresca e attiva. Quando un client riceve i dati, controlla e solleva un’altra richiesta se necessario. Naturalmente, ci sono molteplici vantaggi e casi d’uso per lunghi sondaggi. Ma il polling lungo non è la tecnologia migliore e più sofisticata per la comunicazione client-server. Se la connessione scade, ne sarà richiesta una nuova. Inoltre, il polling lungo può comportare un utilizzo molto scarso delle risorse.
Questi sono due dei principali motivi per cui a era necessaria la tecnologia push. Come suggerisce il nome, il server invia i dati ogni volta che ha qualcosa per il client. Ciò significa che il cliente non deve sollevare richieste periodiche.
Iniziamo la nostra demo con il server web. Questa è una semplice demo che ti aiuterà a iniziare con l’intera tecnologia.
1. Creazione del server Node.js
Passaggio 1: scegli la tua libreria
Quando si tratta di Node.js, hai una dozzina di librerie tra cui scegliere per costruire il server. La mia preferita è ws, una libreria estremamente semplice per la creazione di server. La libreria ci consente di creare sia server che client. Quant’è fico?
Ovviamente, il prerequisito per l’utilizzo di ws sarebbe l’installazione di Node. Quindi, non dimenticare di scaricare e installare Node.js nel tuo sistema.
Successivamente, è necessario installare la libreria. Bene, questo è un lavoro molto semplice in cui esegui il seguente comando:
npm install ws
Quindi apri l’editor di codice più amato e crea un file chiamato index.js.
Passaggio 2: creare il server WebSocket
Per prima cosa, devi importare il file ws
modulo. Questo è piuttosto semplice. Devi digitare la seguente riga e assicurerebbe di importare ws nella tua applicazione.
const WebSocket = require('ws')
Successivamente, devi creare un server web socket su una porta. Il client comunicherà con il server attraverso questa porta. Nel nostro caso, il numero di porta è 8081.
const wss = new WebSocket.Server({ port: 8081 })
Quindi, cosa dovrebbe accadere quando il client vuole comunicare con il server? Dobbiamo chiarire la logica per questo. Il modulo ws viene fornito con più eventi per ciascuno dei seguenti cambiamenti di stato:
open
close
message
connection
upgrade
ping
Inoltre, il modulo viene fornito con alcune funzioni per attivare e gestire gli eventi di cui sopra:
on
send
onerror
Nel nostro server semplice, emetteremmo il file connection
ogni volta che il client si connette. Per emettere uno degli eventi, possiamo utilizzare il file on
funzione.
wss.on('connection', function connection(ws) {});
Nel caso in cui ci sia un errore, il onerror
funzione può essere utilizzata. Ecco un breve esempio di come queste funzioni possono essere utilizzate.
ws.on("close", () => { /* handle the event */ }); ws.onerror = function (error) { /* handle the error */ }
Lo scheletro di base del nostro server WebSocket, che apre e chiude la porta 8081 per consentire al client di connettersi, è il seguente:
const WebSocket = require('ws') const wss = new WebSocket.Server({ port: 8081 }) wss.on('connection', function connection(ws) { ws.on("close", () => { console.log("Client disconnected"); }); ws.onerror = function () { console.log("Some Error occurred"); } });
Passaggio 3: ricezione di un messaggio
Un server può eseguire solo una di queste due operazioni con un client: inviare un messaggio o ricevere un messaggio. Innanzitutto, vediamo come ricevere un messaggio da un client. Una volta stabilita la connessione tra client e server, il server può ricevere un messaggio utilizzando il file message
funzione.
La comunicazione Websocket avviene sempre con i frame. Questi sono frammenti di dati, che vengono trasferiti dal client al server o viceversa. Inoltre, i frammenti di dati possono essere nei seguenti formati:
- Testo telai: questi contengono dati sotto forma di testo non elaborato.
- Binario frame di dati: questi contengono pezzi binari di dati.
- Cornici da ping pong: questi sono principalmente usati per verificare se la connessione è stata stabilita tra il client e il server. Il browser spesso si assume la responsabilità di rispondere a questi messaggi.
- Connessione chiusa telai: questi vengono utilizzati per eseguire l’handshake alla chiusura della connessione.
Quando il browser dialoga con il server, cosa che accade nel nostro caso, vengono utilizzati i frame di testo o binari. il .send()
la funzionalità del client tende a inviare messaggi come dati binari o di testo. Questo include vari formati come ArrayBuffer
e Blob
anche. Non è necessario configurare nulla per inviare i dati in un formato specifico. Basta inviarlo e decodificarlo al server.
Nel frattempo, se vuoi menzionare esplicitamente il tipo di cornice, usa il .binaryType
proprietà della presa.
ws.binaryType = "arraybuffer"
Se vuoi decodificare i dati del buffer, in stringa, puoi usare la seguente funzione. Qui facciamo uso di Buffer.from()
seguito da .toString()
per convertire il buffer in stringa.
ws.on("message", (msg) => { var buf = Buffer.from(msg); console.log(buf.toString()); });
Passaggio 4: invio di un messaggio al cliente
La prossima funzionalità del server è inviare un messaggio al client. Per questo utilizziamo il ws.send()
funzione.
Ora che abbiamo identificato e definito le basi del nostro server, costruiamo l’applicazione in cui il server invia un messaggio al client, ogni volta che il client si connette con esso. Nella parte di codice sottostante, il server continua a inviare 'hello world'
ogni secondo, finché il client non si disconnette.
Ecco quanto è semplice inviare un messaggio al cliente.
const interval = setInterval(() => { ws.send('hello world') }, 1000)
Passaggio 5: eseguire il server
Infine, è necessario eseguire il server. Per questo, è necessario aprire una finestra di terminale, digitare il seguente comando e lasciare il server in esecuzione. Non dimenticare di aprire il terminale nella cartella, dove il file index.js creato nel passaggio 1 è presente.
node index.js
E, l’intero codice del server per connettersi, disconnettersi, inviare e ricevere messaggi, appare come di seguito:
const WebSocket = require('ws') const wss = new WebSocket.Server({ port: 8081 }) wss.on('connection', function connection(ws) { console.log('Client connected') const interval = setInterval(() => { ws.send('hello world') }, 1000) ws.on("close", () => { console.log("Client disconnected"); }); ws.onerror = function () { console.log("Some Error occurred"); } ws.on("message", (msg) => { var buf = Buffer.from(msg); console.log(buf.toString()); }); });
2. Costruire il cliente
Ora che il server è attivo e funzionante, è il momento di creare il client. Per questo, crea un altro progetto Node con i seguenti file:
node_modules index.html index.js package.json
Passaggio 1: installa la libreria
Proprio come abbiamo installato ws per costruire il nostro server, devi installare anche ws nel pacchetto client. Tuo pacchetto.jsondovrebbe avere la seguente dipendenza:
{ "dependencies": { "ws": "^8.8.1" } }
Passaggio 2: connessione al server web
Per connetterci con il server web, dobbiamo inizializzare un nuovo WebSocket. Inoltre, il socket Web deve connettersi alla porta definita durante la creazione del server Web. Nel nostro caso, sarà di nuovo 8081.
var hostURL = "ws://localhost:8081"; webSocket = new WebSocket(hostURL);
Ci sono tre parti importanti nell’URL dell’host.
- schema: ws
- ospite: host locale
- porta: 8081
Insieme a new WebSocket(url)
, la connessione avviene immediatamente. Durante il processo di creazione della connessione, il client (noto anche come browser) utilizza le intestazioni per chiedere al server se i WebSocket sono supportati o meno. Se il server risponde con un sì, la connessione viene stabilita ei due iniziano a parlare. Il protocollo utilizzato è il protocollo WebSocket. Qui noi non utilizzare il protocollo HTTP affatto!
Ecco alcune delle intestazioni della richiesta, nella nostra connessione client-server.
GET ws://localhost:8081/ HTTP/1.1 Host: localhost:8081 Connection: Upgrade . . Upgrade: websocket . Sec-WebSocket-Version: 13 . . Sec-WebSocket-Key: cBtV+sKFkk3wqmFFr909Vg== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
-
Connection: upgrade
dice che il client ha bisogno di un cambio di protocollo. -
Upgrade: websocket
menziona che il protocollo richiesto è “websocket”. -
Sec-WebSocket-Key
è una chiave generata dal browser. Questo è un numero casuale che assicura che il server supporti il protocollo WebSocket. Impedisce inoltre a vari proxy di memorizzare nella cache qualsiasi conversazione effettuata tra il client e il server. -
Sec-WebSocket-Version
identifica la versione del protocollo WebSocket. Il più recente è il 13.
Se il server ha accettato di stabilire una connessione, la risposta sarebbe 101. E le intestazioni di risposta saranno le seguenti:
101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: abcd=
Sec-WebSocket-Accept
ha una chiave generata utilizzando un algoritmo molto speciale. Nel momento in cui il browser (noto anche come client) nota questa chiave, sa che il server supporta effettivamente il protocollo WebSocket. D’ora in poi, i dati possono essere trasferiti sotto forma di frame.
Non puoi emulare WebSocket Handshake. Non puoi usare andare a prendere o XMLHttpRequest per effettuare una richiesta HTTP. Come mai? Perché JavaScript non ha il permesso di impostare le intestazioni sopra menzionate.
Passaggio 3: definire gli eventi WebSocket
Prima di definire i nostri eventi web socket, è necessario comprenderli meglio. Nel nostro client, useremmo tre diversi eventi:
-
onOpen
: Funzionalità da attivare all’apertura del socket. -
onMessage
: Funzionalità da attivare quando si riceve un messaggio dal server. -
onClose
: Funzionalità da attivare quando il server è chiuso.
Gli eventi di cui sopra devono essere chiamati utilizzando l’ WebSocket
oggetto.
webSocket.onopen = function(){} webSocket.onmessage = function(msg){} webSocket.onclose = function(){}
La nostra demo, il client si collegherà con il server e visualizzerà qualsiasi messaggio ricevuto dal server sulla pagina HTML. Allo stesso modo, qualsiasi cambiamento di stato dalla connessione alla disconnessione verrà stampato sulla pagina HTML. Per raggiungere questo obiettivo, scriveremo a connect
metodo, che implementerà di conseguenza gli eventi Web Socket.
function connect(){ try{ webSocket = new WebSocket(hostURL); messageDiv.innerHTML = "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; webSocket.onopen = function(){ messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; connectBtn.disabled = true; disconnectBtn.disabled = false; } webSocket.onmessage = function(msg){ messageDiv.innerHTML += "<p>Server response : " + msg.data + "</p>"; } webSocket.onclose = function(){ messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; connectBtn.disabled = false; disconnectBtn.disabled = true; } }catch(exception){ messageDiv.innerHTML += 'Exception happen, ' + exception; } }
Puoi vedere che la nostra funzione di connessione ha un blocco try/catch. È buona pratica di codifica racchiudere tutte le comunicazioni del server all’interno del blocco try/catch. Se qualcosa va storto, dobbiamo avere una strategia di ripiego. E try/catch ci offre questo! Fornisce al client un modo per far sapere all’utente che qualcosa è andato storto con la connessione. Inoltre è un ottimo posto per eseguire il debug del flusso complessivo.
Nel metodo di cui sopra, il onmessage
La funzione assume il ruolo di stampare qualsiasi messaggio dal server sulla pagina HTML.
Passaggio 4: il ponte
La funzione di connessione non avvia immediatamente la connessione client-server. Possiamo vedere che il websocket
è definito, ma la definizione del messageDiv
, connectBtn
, disconnectBtn
e hostUrl
sembra provenire da un’altra parte.
Abbiamo suddiviso il codice client in due sezioni, init()
e connect()
. È responsabilità del init
funzione per caricare tutte queste variabili. E il init
la funzione deve essere caricata quando la pagina viene caricata. La definizione del init
la funzione è riportata di seguito.
function init(){ messageDiv = document.getElementById("message"); textInput = document.getElementById("text"); hostURL = "ws://localhost:8081"; websocketReadyStateArray = new Array('Connecting', 'Connected', 'Closing', 'Closed'); connectBtn = document.getElementById('connect'); disconnectBtn = document.getElementById('disconnect'); connectBtn.disabled = false; sendTextBtn.disabled = true; sendJSONObjectBtn.disabled = true; disconnectBtn.disabled = true; }
Passaggio 5: la pagina del cliente
La pagina del cliente è piuttosto semplice e diretta. Avremo quanto segue:
- un
div
dove verrà caricato il messaggio dal server - Due
button
s per connettersi e disconnettersi dal server
Ecco un codice HTML, per costruire questa pagina. Deve essere inserito indice.html:
<!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Html5 WebSockets Example</title> <script type="text/javascript" src="https://code.tutsplus.com/tutorials/index.js" charset="utf-8"></script> <style> .block{ display:block; margin-top: 10px; } </style> </head> <body onload="init()"> <h3>Html5 WebSockets Example.</h3> <div id="message" class="block"></div> <button id="connect" onclick="connect()">Connect</button> <button id="disconnect" onclick="disconnect()">Disconnect</button> </body> </html>
Non appena viene stabilita la connessione, il client riceverà “Hello World” dal server. Ora, la pagina apparirà come sotto.
Il pezzo di codice completo in client’s index.js è come segue:
var webSocket; var messageDiv; var textInput; var hostURL; var websocketReadyStateArray; var connectBtn; var disconnectBtn; function init(){ messageDiv = document.getElementById("message"); textInput = document.getElementById("text"); hostURL = "ws://localhost:8081"; websocketReadyStateArray = new Array('Connecting', 'Connected', 'Closing', 'Closed'); connectBtn = document.getElementById('connect'); disconnectBtn = document.getElementById('disconnect'); connectBtn.disabled = false; sendTextBtn.disabled = true; sendJSONObjectBtn.disabled = true; disconnectBtn.disabled = true; } function connect(){ try{ webSocket = new WebSocket(hostURL); messageDiv.innerHTML = "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; webSocket.onopen = function(){ messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; connectBtn.disabled = true; disconnectBtn.disabled = false; } webSocket.onmessage = function(msg){ messageDiv.innerHTML += "<p>Server response : " + msg.data + "</p>"; } webSocket.onclose = function(){ messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>"; connectBtn.disabled = false; disconnectBtn.disabled = true; } }catch(exception){ messageDiv.innerHTML += 'Exception happen, ' + exception; } } function selectAll(){ textInput.select(); } function disconnect(){ webSocket.close(); }
Passaggio 6: invio di dati dal client al server
Fino a quando, il pezzo di codice sopra, sarai in grado di inviare dati dal server al client. Per inviare i dati dal client al server, devi implementare poche righe di codice in più.
Stiamo per aggiungere una casella di testo, nella nostra pagina HTML in cui l’utente può inserire i dati. E un pulsante per inviare il contenuto della casella di testo al server quando viene cliccato.
<p class="block">Please input some text to Send : <input type="text" id="text" onfocus="selectAll()"/></p> <!-- ... --> <button id="sendMessage" onclick="sendMessage()">Send Message</button>
Quando si fa clic sul pulsante, viene richiamato il seguente metodo per inviare un messaggio al server. Poiché viene utilizzato il frame predefinito del web socket, il messaggio verrà inviato come a Buffer
.
function sendMessage(){ webSocket.send(textInput.value) }
Al clic Invia messaggioquanto segue viene visualizzato nella console del server, come di seguito:
Passaggio 7: eseguire il client
Per eseguire il client, non devi fare molto. Devi aprire indice.html nel tuo browser preferito, quindi fai clic su Collegare per stabilire la connessione con il server.
Questo è tutto!
Conclusione
Questo ci porta alla fine del nostro tutorial sui WebSocket utilizzando HTML e Javascript (NodeJS). I WebSocket sono estremamente entusiasmanti e sono cambiati drasticamente negli ultimi anni. WS è solo una delle tante librerie web socket tra cui scegliere. Devi tieni d’occhio il W3C WebSocket API, per conoscere tutte le ultime modifiche a questa tecnologia PUSH.
WebSocket è un modo persistente per stabilire una connessione browser-server. Questi non hanno limiti di origine incrociata e sono supportati in tutti i browser moderni. L’API è semplice con metodi come .send
e .close
.