¿Cuáles son las diferencias entre socket.io y websockets en
node.js?
¿Son ambas tecnologías de empuje del servidor?
Las únicas diferencias que sentí fueron,
socket.io me permitía enviar/emitir mensajes especificando un nombre de evento.
En el caso de socket.io un mensaje del servidor llegará a todos los clientes, pero para lo mismo en websockets me vi obligado a mantener un array de todas las conexiones y hacer un bucle a través de él para enviar mensajes a todos los clientes.
Además, me pregunto por qué los inspectores web (como Chrome/firebug/fiddler) no son capaces de captar estos mensajes (de socket.io/websocket) del servidor.
Por favor, aclare esto.
Hay algunos conceptos erróneos comunes con respecto a WebSocket y Socket.IO:
El primer concepto erróneo es que el uso de Socket.IO es significativamente más fácil que el uso de WebSocket, lo cual no parece ser el caso. Vea los ejemplos siguientes.
El segundo concepto erróneo es que WebSocket no está ampliamente soportado en los navegadores. Ver más abajo para más información.
La tercera idea errónea es que Socket.IO rebaja la conexión como un recurso en los navegadores más antiguos. En realidad asume que el navegador es antiguo e inicia una conexión AJAX con el servidor, que se actualiza posteriormente en los navegadores que soportan WebSocket, después de que se intercambie algo de tráfico. Ver abajo para más detalles.
Escribí un módulo npm para demostrar la diferencia entre WebSocket y Socket.IO:
Es un ejemplo simple de código del lado del servidor y del lado del cliente - el cliente se conecta al servidor usando WebSocket o Socket.IO y el servidor envía tres mensajes en intervalos de 1s, que son agregados al DOM por el cliente.
Compara el ejemplo del lado del servidor usando WebSocket y Socket.IO para hacer lo mismo en una aplicación Express.js:
Ejemplo de servidor WebSocket usando Express.js:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
Fuente: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js
Ejemplo de servidor Socket.IO usando Express.js:
var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
console.error('socket.io connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');
Fuente: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js
Compara el ejemplo del lado del cliente de usar WebSocket y Socket.IO para hacer lo mismo en el navegador:
Ejemplo de cliente WebSocket usando vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
Fuente: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html
Ejemplo de cliente Socket.IO usando JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
Fuente: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html
Para ver la diferencia en el tráfico de red puedes ejecutar mi prueba. Aquí están los resultados que obtuve:
De esas 2 peticiones:
(La solicitud de actualización de la conexión es visible en las herramientas del desarrollador con una respuesta 101 Switching Protocols).
De esas 6 peticiones:
Resultados de WebSocket que obtuve en localhost:
[]
Resultados de Socket.IO que obtuve en localhost:
[]
Inicio rápido:
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
Abre http://localhost:3001/ en tu navegador, abre las herramientas de desarrollo con Shift+Ctrl+I, abre la pestaña de Red y recarga la página con Ctrl+R para ver el tráfico de red de la versión WebSocket.
Abre http://localhost:3002/ en tu navegador, abre las herramientas de desarrollo con Shift+Ctrl+I, abre la pestaña Red y recarga la página con Ctrl+R para ver el tráfico de red para la versión Socket.IO.
Para desinstalar:
# Uninstall:
npm rm -g websocket-vs-socket.io
A partir de junio de 2016, WebSocket funciona en todo, excepto en Opera Mini, incluyendo IE superior a 9.
Esta es la compatibilidad de navegadores de WebSocket en Can I Use a partir de junio de 2016:
[]
Consulte http://caniuse.com/websockets para obtener información actualizada.
Sus ventajas son que simplifica el uso de WebSockets tal y como lo has descrito en el punto 2, y probablemente lo más importante es que proporciona fail-overs a otros protocolos en el caso de que WebSockets no esté soportado en el navegador o el servidor. Yo evitaría usar WebSockets directamente a menos que estés muy familiarizado con los entornos en los que no funcionan y seas capaz de trabajar alrededor de esas limitaciones.
Esta es una buena lectura sobre WebSockets y Socket.IO.
Voy a proporcionar un argumento contra el uso de socket.io.
Creo que usar socket.io sólo porque tiene fallbacks no es una buena idea. Deje que IE8 RIP.
En el pasado ha habido muchos casos en los que las nuevas versiones de NodeJS han roto socket.io. Puedes consultar estas listas para ver ejemplos... https://github.com/socketio/socket.io/issues?q=install+error
Si vas a desarrollar una aplicación para Android o algo que necesita trabajar con tu aplicación existente, probablemente estarías bien trabajando con WS de inmediato, socket.io podría darte algunos problemas allí...
Además el módulo WS para Node.JS es increíblemente sencillo de usar.
Usar Socket.IO es básicamente como usar jQuery - si quieres apoyar a los navegadores más antiguos, necesitas escribir menos código y la biblioteca proveerá de respaldos. Socket.io utiliza la tecnología de los webckets si está disponible, y si no, comprueba el mejor tipo de comunicación disponible y lo utiliza.
Socket.IO usa WebSocket y cuando WebSocket no está disponible usa algo de respaldo para hacer conexiones en tiempo real.
Incluso si los navegadores modernos soportan WebSockets ahora, creo que no hay necesidad de tirar SocketIO y todavía tiene su lugar en cualquier proyecto de hoy en día. Es fácil de entender, y personalmente, aprendí cómo funcionan los WebSockets gracias a SocketIO.
Como se ha dicho en este tema, hay un montón de librerías de integración para Angular, React, etc. y tipos de definición para TypeScript y otros lenguajes de programación.
El otro punto que añadiría a las diferencias entre Socket.io y WebSockets es que la agrupación con Socket.io no es gran cosa. Socket.io ofrece [Adaptadores][1] que pueden ser usados para enlazarlo con Redis para mejorar la escalabilidad. Tienes [ioredis][2] y [socket.io-redis][3] por ejemplo.
Sí, lo sé, [SocketCluster][4] existe, pero eso's fuera de tema.
[1]: https://socket.io/docs/using-multiple-nodes/#passing-events-between-nodes [2]: https://github.com/luin/ioredis [3]: https://github.com/socketio/socket.io-redis [4]: https://github.com/SocketCluster/socketcluster