WebSocket in Node.js: server, client, heartbeat e riconnessione

WebSocket in Node.js: server ws, client integrato, heartbeat | We.Inc

Crea un server WebSocket in Node.js con il pacchetto ws, connettiti con il client WebSocket integrato in Node, rileva i socket morti con ping e pong e riconnettiti con backoff.

Node.js non ha un server WebSocket integrato, quindi la maggior parte dei progetti installa il pacchetto ws e crea un WebSocketServer. Per il lato client, Node include un WebSocket globale compatibile con il browser, aggiunto in v21.0.0 e v20.10.0, senza flag da v22.0.0 e dichiarato stabile in v22.4.0. Aggiungi un heartbeat con ping e pong e la riconnessione con backoff prima di andare in produzione.

Quale parte fa cosa

Questa guida costruisce un piccolo server in stile chat e i client che ci parlano, in quest'ordine: un server che fa echo e broadcast, uno script Node che si connette senza alcuna dipendenza, un heartbeat che scarta le connessioni morte in silenzio e un client che ritorna dopo il riavvio del server. Il calcolatore qui sotto mostra come crescono i ritardi tra i tentativi prima che tu li metta nel codice.

Domande frequenti

Node.js ha WebSocket integrato?

Solo il client. La classe globale WebSocket è comparsa in v21.0.0 e v20.10.0 dietro il flag --experimental-websocket, ha perso il flag in v22.0.0 e non è più sperimentale da v22.4.0. Non esiste ancora un server integrato, ed è per questo che ws resta la scelta abituale.

Devo usare ws o Socket.IO?

ws parla il protocollo WebSocket puro, quindi qualsiasi client standard può connettersi, compresi il browser e il globale di Node. Socket.IO aggiunge sopra un suo protocollo, con stanze e riconnessione automatica, ma richiede la sua libreria client dall'altra parte.

Perché le connessioni muoiono senza un evento close?

Se un percorso di rete sparisce, ad esempio quando si chiude il coperchio di un portatile, nessun frame di chiusura viene inviato e il server tiene un socket semiaperto. L'heartbeat li trova: un socket che non ha risposto all'ultimo ping viene terminato al giro successivo.

Un client browser può inviare ping?

No. L'API del browser ha solo send() e close(). I browser però rispondono da soli ai ping del server con dei pong, ed è per questo che l'heartbeat lato server funziona anche con i client browser.

Come condivido una porta con un server HTTP?

Crea tu il server HTTP, ad esempio con Express o node:http, poi passalo come new WebSocketServer({ server }). Le richieste di upgrade vanno a ws e quelle normali alla tua app.

Come inizia una connessione

Gli heartbeat spiegati semplice

Riconnettersi senza martellare il server

Passo 1: un server con ws

server.js: echo e broadcast

Ogni messaggio viene rimandato a tutti i client aperti. Il listener error evita che un singolo socket difettoso faccia crashare il processo.

Passo 2: un client senza dipendenze

client.js: il WebSocket globale di Node

Funziona senza modifiche su Node 22 o successivo e nella console di un browser, perché entrambi espongono la stessa classe WebSocket.

Passo 3: eliminare le connessioni morte con ping e pong

La nostra versione dello schema del README di ws: segna come vivo al pong, termina tutto ciò che ha saltato l'ultimo giro.

Passo 4: un client che si riconnette

reconnect.js: backoff esponenziale con jitter

Il ritardo raddoppia dopo ogni tentativo fallito fino a un tetto, riceve una variazione casuale e si azzera quando una connessione si apre.

Dietro nginx

nginx lascia passare l'upgrade solo se inoltri tu gli header Upgrade e Connection. Prima di nginx 1.29.7 serve anche proxy_http_version 1.1.

Location nginx per il socket

proxy_read_timeout alza il limite di inattività di 60 secondi; l'heartbeat qui sopra mantiene comunque il traffico attivo.

Calcolatore del ritardo di riconnessione

Imposta un primo ritardo, un moltiplicatore e un tetto per vedere quanto aspetta un client prima di ogni tentativo, e l'attesa più breve e più lunga una volta aggiunto il jitter.

Primo ritardo (ms)

Moltiplicatore

Tetto (ms)

Tentativi da mostrare

Aggiungi jitter (attesa tra metà e l'intero ritardo)

Attesa prima di ogni tentativo di riconnessione

Tentativo

Ritardo

Con jitter

Attesa totale finora

da {n} a {v} s

Le stesse impostazioni come codice

Inizia gratis · Nessuna carta di credito richiesta

Correlati: Guide

Prodotto

Per chi è

Funzionalità

Risorse

Azienda

Mappa del sito