Socket.IO è una libreria per la comunicazione bidirezionale in tempo reale tra client e server basata su WebSocket con fallback automatico. Fornisce un trasporto affidabile per il trasferimento istantaneo dei dati in chat, giochi ed editor collaborativi. Secondo la documentazione ufficiale di Socket.IO (2024), la libreria gestisce oltre un milione di connessioni su un singolo server con una configurazione adeguata.
Punti chiave
Socket.IO è una libreria JavaScript open source per la comunicazione bidirezionale basata su eventi tra client e server. È stata creata nel 2010 dallo sviluppatore Guillermo Rauch e da allora è diventata lo standard de facto per le applicazioni in tempo reale su Node.js.
A differenza dell'API WebSocket nativa, Socket.IO fornisce astrazioni aggiuntive: stanze, namespace, riconnessione automatica e tipi di dati binari. La libreria non è un'implementazione separata di WebSocket — utilizza Engine.IO come livello di trasporto, che prima stabilisce una connessione HTTP long-polling e poi tenta di fare upgrade a WebSocket.
Secondo le statistiche npm (2025), vengono scaricate oltre 12 milioni di copie del pacchetto socket.io ogni settimana, rendendola una delle librerie più popolari nell'ecosistema Node.js. Socket.IO è supportato su tutte le piattaforme moderne: browser, iOS, Android, React Native e applicazioni desktop.
Socket.IO versione 1.0 è stata rilasciata nel 2014 e ha introdotto il concetto di namespace, che consentono di multiplexare più canali logici attraverso una singola connessione TCP. La versione 2.0 (2017) ha aggiunto il supporto per i dati binari e migliorato le prestazioni di parsing. La versione attuale 4.x (2020–2025) include il supporto completo per TypeScript, una modalità adattatore principale per la scalabilità e una migliore retrocompatibilità.
Ogni versione principale mantiene la retrocompatibilità dell'API — un client socket.io@2 può connettersi a un server socket.io@4 attraverso una modalità di compatibilità speciale. Questo è importante per progetti di lunga durata in cui gli aggiornamenti lato client avvengono gradualmente.
L'architettura di Socket.IO è composta da due componenti: il modulo server (pacchetto npm socket.io) e il modulo client (pacchetto npm socket.io-client). Il server funziona su un server HTTP(S) Node.js e utilizza Engine.IO per gestire il livello di trasporto.
Alla connessione iniziale, il client invia una richiesta HTTP al server. Engine.IO risponde e stabilisce una connessione long-polling. Dopodiché, il client invia una richiesta per aggiornare il protocollo di trasporto a WebSocket. Se il server supporta WebSocket, l'aggiornamento avviene all'interno di una singola sessione TCP. In caso contrario, la connessione rimane su long-polling e il codice dell'applicazione non richiede modifiche.
Secondo i test delle prestazioni di Socket.IO (2024), utilizzando WebSocket, la latenza è di 2–5 ms per trasmissione di messaggio, mentre il long-polling aggiunge 150–300 ms a causa dell'overhead HTTP. La scelta del trasporto è trasparente per lo sviluppatore.
Engine.IO è il livello di trasporto di basso livello su cui è costruito Socket.IO. Si occupa dell'stabilimento della connessione, della selezione del trasporto, dell'heartbeat (ping/pong) e della terminazione della connessione. I principali tipi di pacchetti Engine.IO sono: open (inizializzazione), close (chiusura), ping/pong (keep-alive), upgrade (cambio di trasporto) e message (dati).
Socket.IO costruisce il suo modello basato su eventi su Engine.IO — è con questo che lo sviluppatore lavora. Ogni messaggio Socket.IO viene incapsulato in un pacchetto Engine.IO di tipo message con un identificatore univoco per la conferma di consegna.
Socket.IO fornisce un insieme di funzionalità che non sono presenti nell'API WebSocket nativa e che rendono lo sviluppo di applicazioni in tempo reale significativamente più semplice. Vediamo le principali.
Riconnessione automatica — il client ripristina automaticamente la connessione in caso di interruzione con backoff esponenziale (100 ms, 200 ms, 400 ms... fino a un massimo). Secondo la documentazione di Socket.IO (2024), le impostazioni di ripetizione sono disponibili tramite i parametri reconnectionDelay e reconnectionAttempts. Questa opzione è fondamentale per le applicazioni mobili dove la connessione può essere interrotta durante i cambi di rete.
Supporto delle stanze — il server può raggruppare i socket in stanze e inviare messaggi solo ai partecipanti di una stanza specifica. Le stanze non richiedono creazione esplicita — vengono create quando il primo socket vi si unisce. Le stanze sono implementate a livello di processo e non sono condivise tra server diversi senza un adattatore speciale.
Namespace — separazione logica dei canali di comunicazione su una singola connessione. Ad esempio, il namespace /chat per i messaggi di chat e /notifications per le notifiche. Ogni namespace ha le proprie stanze, middleware e gestori. I namespace vengono multiplexati su una singola connessione TCP, risparmiando risorse.
Conferma di consegna — quando si invia un messaggio, è possibile passare una funzione callback che verrà chiamata quando il server conferma la ricezione. Questo è implementato tramite un identificatore univoco per ogni pacchetto. Il meccanismo di conferma garantisce che i messaggi criticamente importanti (ad esempio, transazioni di pagamento) vengano consegnati al destinatario.
La scelta tra Socket.IO e WebSocket nativo dipende dai requisiti del progetto. WebSocket è un protocollo standardizzato (RFC 6455) supportato da tutti i browser moderni. Socket.IO è una libreria che utilizza WebSocket come trasporto ma aggiunge funzionalità aggiuntive.
| Caratteristica | Socket.IO | WebSocket |
|---|---|---|
| Trasporto | WebSocket + HTTP long-polling (fallback) | Solo WebSocket |
| Modello eventi | Eventi nominati con payload JSON | Solo frame testo/binari |
| Stanze | Raggruppamento socket integrato | Richiede implementazione manuale |
| Riconnessione automatica | Integrata | Richiede implementazione manuale |
| Conferma di consegna | Meccanismo ACK con callback | Disponibile tramite estensioni del protocollo |
| Scalabilità | Adattatori (Redis, MongoDB, Cluster) | Richiede infrastruttura personalizzata |
| Dimensione libreria | ~50 KB (client, gzip) | Integrato nel browser (0 KB) |
Se il tuo progetto richiede massime prestazioni e dimensioni minime del client — scegli WebSocket nativo. Se hai bisogno di consegna affidabile, raggruppamento e un modello basato su eventi — Socket.IO ridurrà i tempi di sviluppo di 2–3 volte grazie alle astrazioni pronte all'uso.
Secondo il sondaggio State of JS 2024, il 67% degli sviluppatori di applicazioni in tempo reale preferisce Socket.IO per la sua API comoda e la gestione integrata dei casi limite (disconnessione di rete, riconnessione, dati binari).
Installare Socket.IO richiede due pacchetti: lato server e lato client. Vediamo la configurazione di base per un progetto Node.js. Il server crea un server HTTP, inizializza Socket.IO e gestisce gli eventi di connessione e disconnessione dei client.
Secondo la documentazione di Socket.IO (2024), il server può essere avviato senza Express utilizzando il modulo http integrato, ma nei progetti reali si usa solitamente Express o Fastify per il routing delle richieste HTTP.
const express = require('express');
const http = require('http');
const Server = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: { origin: '*' }
});
io.on('connection', (socket) => {
console.log('Client connesso:', socket.id);
socket.emit('welcome', { message: 'Hello from server' });
socket.on('disconnect', () => {
console.log('Client disconnesso');
});
});
server.listen(3000, () => {
console.log('Server in esecuzione sulla porta 3000');
});
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000', {
transports: ['websocket', 'polling'],
reconnectionDelay: 1000
});
socket.on('welcome', (data) => {
console.log(data.message);
});
socket.emit('chat message', {
user: 'Alice',
text: 'Hello everyone!'
});
Il modello di eventi di Socket.IO si basa su eventi nominati. Il server e il client inviano e ricevono messaggi legati a un nome di evento specifico. Il payload può essere una stringa, un oggetto JSON o dati binari (Buffer, ArrayBuffer, Blob).
Ogni evento supporta ACK (acknowledgement) — il passaggio di una funzione callback che viene eseguita sul lato del mittente dopo che l'evento è stato elaborato dal destinatario. Ciò consente di implementare un pattern richiesta-risposta sul modello di eventi. ACK funziona solo se il destinatario chiama esplicitamente il callback.
Secondo la documentazione di Socket.IO (2024), la dimensione massima di un singolo messaggio non deve superare 1 MB per prestazioni ottimali. I messaggi più grandi dovrebbero essere suddivisi in frammenti o inviati tramite un canale separato.
io.on('connection', (socket) => {
socket.join('room-1');
socket.to('room-1').emit('user joined', {
userId: socket.id
});
io.to('room-1').emit('message', {
text: 'Broadcast to room'
});
socket.leave('room-1');
});
La scalabilità orizzontale di Socket.IO richiede di risolvere il problema della condivisione dello stato tra più processi server. Stanze, namespace e l'elenco dei socket connessi sono memorizzati nella memoria di un singolo processo e non sono visibili agli altri processi senza un adattatore.
Adattatori ufficiali di Socket.IO: redis (tramite Redis Pub/Sub), mongodb (tramite MongoDB change streams), cluster (per la modalità multiprocesso di Node.js cluster). L'adattatore funge da intermediario di messaggi tra le istanze di Socket.IO. Quando un evento viene inviato a una stanza, l'adattatore lo pubblica su Redis e tutti i server ricevono la notifica.
Secondo i test di carico di Socket.IO (2024), un cluster di 4 server con l'adattatore Redis gestisce fino a 400.000 connessioni simultanee con una latenza inferiore a 10 ms. Senza adattatore, la capacità massima di un singolo processo Node.js è di circa 100.000 connessioni con 1 GB di memoria.
const Server = require('socket.io');
const RedisAdapter = require('@socket.io/redis-adapter');
const Redis = require('ioredis');
const pubClient = new Redis({ host: 'localhost', port: 6379 });
const subClient = pubClient.duplicate();
const io = new Server(server);
io.adapter(RedisAdapter(pubClient, subClient));
Quando si utilizza Kubernetes o Docker Swarm, si consiglia di configurare ulteriormente l'affinità di sessione (sticky session) in modo che le richieste dello stesso client arrivino allo stesso server; altrimenti, l'assegnazione potrebbe cambiare ad ogni riconnessione.
Domande frequenti
Socket.IO fornisce un modello di eventi con eventi nominati, riconnessione automatica, supporto delle stanze e fallback su HTTP long-polling. Il WebSocket nativo è un protocollo di basso livello con un'API minima che richiede l'implementazione manuale di questi meccanismi.
Sì, esistono implementazioni di terze parti della parte server per Python (python-socketio), Java (netty-socketio), Go (go-socketio) e altri linguaggi. Il client socket.io-client è disponibile per JavaScript, Swift, Kotlin e C++.
Un singolo processo Node.js con Socket.IO gestisce fino a 100.000 connessioni con 1 GB di RAM. Con l'adattatore Redis e 4 server, il cluster può gestire fino a 400.000 client simultanei.
Sì, per iOS esiste un client ufficiale in Swift, per Android — un client in Java/Kotlin. Per React Native, viene utilizzato il client JavaScript standard socket.io-client.
Usa HTTPS/WSS invece di HTTP/WS, configura middleware per l'autenticazione tramite token (JWT), imposta limiti di eventi in uscita tramite validatori e utilizza il rate limiting per la protezione DDoS.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.