Versión npmBuildConstrucción Windows x86Estado de la cobertura

ws es una herramienta sencilla de usar, muy rápido, y probado a fondo la implementación de cliente y servidor de WebSocket.

Pasa la bastante extensa suite de pruebas de Autobahn: servidor,cliente.

Nota: Este módulo no funciona en el navegador. El cliente en los docs es una referencia a un back end con el rol de cliente en la comunicación WebSocket. Los clientes del navegador deben usar el objeto nativoWebSocket. Para que el mismo código funcione sin problemas en Node.js y en el navegador, puedes utilizar uno de los muchos wrappers disponibles en npm, comoisomorphic-ws.

Tabla de contenidos

  • Soporte de protocolos
  • Instalación
    • Opt-para el rendimiento y el cumplimiento de las especificaciones
  • Documentos de la API
  • Compresión de WebSocket
  • Ejemplos de uso
  • Envío y recepción de datos de texto
  • Envío de datos binarios datos binarios
  • Servidor simple
  • Servidor HTTP/S externo
  • Múltiples servidores que comparten un único servidor HTTP/S
  • Autenticación de clientes
  • Difusión de servidores
  • Demo.websocket.org demo
  • Utilizar la API de streams de Node.js streams API
  • Otros ejemplos
  • Preguntas frecuentes

  • ¿Cómo obtener la dirección IP del cliente?
  • ¿Cómo detectar y cerrar conexiones rotas?
  • ¿Cómo conectarse a través de un proxy?
  • Changelog
  • Licencia
  • Soporte de protocolos

    • Los borradores HyBi 07-12 (Utiliza la opción protocolVersion: 8)
    • Los borradores HyBi 13-17 (Actual por defecto, alternativamente la opciónprotocolVersion: 13)

    Instalación

    npm install ws

    Optar por el rendimiento y el cumplimiento de las especificaciones

    Hay 2 módulos opcionales que se pueden instalar junto con el wsmodule. Estos módulos son complementos binarios que mejoran ciertas operaciones.Los binarios precompilados están disponibles para las plataformas más populares por lo que no es necesario tener un compilador de C++ instalado en su máquina.

    • npm install --save-optional bufferutil: Permite realizar de forma eficiente operaciones como enmascarar y desenmascarar la carga útil de datos de los WebSocketframes.
    • npm install --save-optional utf-8-validate: Permite comprobar de forma eficiente si un mensaje contiene UTF-8 válido como requiere la especificación.

    Documentación de la API

    Vea /doc/ws.md para una documentación similar a la de Node.js de las clases ws y las funciones de utilidad.

    Compresión de WebSocket

    ws soporta la extensión permessage-deflate que permite al cliente y al servidor negociar un algoritmo de compresión y sus parámetros, y luego aplicarlo selectivamente a las cargas de datos de cada mensaje de WebSocket.

    La extensión está desactivada por defecto en el servidor y activada por defecto en el cliente. Añade una sobrecarga significativa en términos de rendimiento y consumo de memoria, por lo que sugerimos habilitarla sólo si es realmente necesaria.

    Tenga en cuenta que Node.js tiene una variedad de problemas con la compresión de alto rendimiento, donde el aumento de la concurrencia, especialmente en Linux, puede conducir a una fragmentación catastrófica de la memoria y un rendimiento lento. Si tiene la intención de utilizar permessage-deflate en producción, vale la pena configurar una prueba representativa de su carga de trabajo y asegurarse de que Node.js/zlib la manejará con un rendimiento y un uso de memoria aceptables.

    El ajuste de permessage-deflate puede realizarse a través de las opciones definidas a continuación. También puede utilizar zlibDeflateOptions y zlibInflateOptions, que se pasa directamente a la creación de flujos raw deflate/inflate.

    Vea los documentos para más opciones.

    const WebSocket = require('ws');const wss = new WebSocket.Server({ port: 8080, perMessageDeflate: { zlibDeflateOptions: { // See zlib defaults. chunkSize: 1024, memLevel: 7, level: 3 }, zlibInflateOptions: { chunkSize: 10 * 1024 }, // Other options settable: clientNoContextTakeover: true, // Defaults to negotiated value. serverNoContextTakeover: true, // Defaults to negotiated value. serverMaxWindowBits: 10, // Defaults to negotiated value. // Below options specified as default values. concurrencyLimit: 10, // Limits zlib concurrency for perf. threshold: 1024 // Size (in bytes) below which messages // should not be compressed. }});

    El cliente sólo utilizará la extensión si está soportada y habilitada en el servidor. Para desactivar siempre la extensión en el cliente establece la opciónperMessageDeflate a false.

    const WebSocket = require('ws');const ws = new WebSocket('ws://www.host.com/path', { perMessageDeflate: false});

    Ejemplos de uso

    Enviar y recibir datos de texto

    const WebSocket = require('ws');const ws = new WebSocket('ws://www.host.com/path');ws.on('open', function open() { ws.send('something');});ws.on('message', function incoming(data) { console.log(data);});

    .

    Envío de datos binarios

    const WebSocket = require('ws');const ws = new WebSocket('ws://www.host.com/path');ws.on('open', function open() { const array = new Float32Array(5); for (var i = 0; i < array.length; ++i) { array = i / 2; } ws.send(array);});

    Servidor simple

    const WebSocket = require('ws');const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', function connection(ws) { ws.on('message', function incoming(message) { console.log('received: %s', message); }); ws.send('something');});

    Externo Servidor HTTP/S

    const fs = require('fs');const https = require('https');const WebSocket = require('ws');const server = https.createServer({ cert: fs.readFileSync('/path/to/cert.pem'), key: fs.readFileSync('/path/to/key.pem')});const wss = new WebSocket.Server({ server });wss.on('connection', function connection(ws) { ws.on('message', function incoming(message) { console.log('received: %s', message); }); ws.send('something');});server.listen(8080);

    Múltiples servidores que comparten un único servidor HTTP/S

    const http = require('http');const WebSocket = require('ws');const url = require('url');const server = http.createServer();const wss1 = new WebSocket.Server({ noServer: true });const wss2 = new WebSocket.Server({ noServer: true });wss1.on('connection', function connection(ws) { // ...});wss2.on('connection', function connection(ws) { // ...});server.on('upgrade', function upgrade(request, socket, head) { const pathname = url.parse(request.url).pathname; if (pathname === '/foo') { wss1.handleUpgrade(request, socket, head, function done(ws) { wss1.emit('connection', ws, request); }); } else if (pathname === '/bar') { wss2.handleUpgrade(request, socket, head, function done(ws) { wss2.emit('connection', ws, request); }); } else { socket.destroy(); }});server.listen(8080);

    Autenticación de clientes

    const http = require('http');const WebSocket = require('ws');const server = http.createServer();const wss = new WebSocket.Server({ noServer: true });wss.on('connection', function connection(ws, request, client) { ws.on('message', function message(msg) { console.log(`Received message ${msg} from user ${client}`); });});server.on('upgrade', function upgrade(request, socket, head) { // This function is not defined on purpose. Implement it with your own logic. authenticate(request, (err, client) => { if (err || !client) { socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); socket.destroy(); return; } wss.handleUpgrade(request, socket, head, function done(ws) { wss.emit('connection', ws, request, client); }); });});server.listen(8080);

    También puedes ver el ejemplo proporcionado utilizando express-session.

    Difusión del servidor

    Un cliente WebSocket emitiendo a todos los clientes WebSocket conectados, incluyéndose a sí mismo.

    const WebSocket = require('ws');const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', function connection(ws) { ws.on('message', function incoming(data) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(data); } }); });});

    Un cliente WebSocket emitiendo a todos los demás clientes WebSocket conectados, excluyéndose a sí mismo.

    const WebSocket = require('ws');const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', function connection(ws) { ws.on('message', function incoming(data) { wss.clients.forEach(function each(client) { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(data); } }); });});

    Demo de echo.websocket.org

    const WebSocket = require('ws');const ws = new WebSocket('wss://echo.websocket.org/', { origin: 'https://websocket.org'});ws.on('open', function open() { console.log('connected'); ws.send(Date.now());});ws.on('close', function close() { console.log('disconnected');});ws.on('message', function incoming(data) { console.log(`Roundtrip time: ${Date.now() - data} ms`); setTimeout(function timeout() { ws.send(Date.now()); }, 500);});

    Utiliza la API de streams de Node.js streams API

    const WebSocket = require('ws');const ws = new WebSocket('wss://echo.websocket.org/', { origin: 'https://websocket.org'});const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' });duplex.pipe(process.stdout);process.stdin.pipe(duplex);

    Otros ejemplos

    Para un ejemplo completo con un cliente de navegador que se comunica con un servidor ws, consulta la carpetaexamples.

    De lo contrario, consulta los casos de prueba.

    Preguntas frecuentes

    ¿Cómo obtener la dirección IP del cliente?

    La dirección IP remota se puede obtener del socket raw.

    const WebSocket = require('ws');const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', function connection(ws, req) { const ip = req.socket.remoteAddress;});

    Cuando el servidor se ejecuta detrás de un proxy como NGINX, el estándar de facto es utilizar la cabecera X-Forwarded-For.

    wss.on('connection', function connection(ws, req) { const ip = req.headers.split(/\s*,\s*/);});

    ¿Cómo detectar y cerrar conexiones rotas?

    A veces el enlace entre el servidor y el cliente puede interrumpirse de una manera que mantiene tanto al servidor como al cliente sin saber el estado roto de laconexión (por ejemplo, al tirar del cable).

    En estos casos se pueden utilizar mensajes de ping como medio para verificar que el punto final remoto sigue respondiendo.

    const WebSocket = require('ws');function noop() {}function heartbeat() { this.isAlive = true;}const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', function connection(ws) { ws.isAlive = true; ws.on('pong', heartbeat);});const interval = setInterval(function ping() { wss.clients.forEach(function each(ws) { if (ws.isAlive === false) return ws.terminate(); ws.isAlive = false; ws.ping(noop); });}, 30000);wss.on('close', function close() { clearInterval(interval);});

    Los mensajes de ping se envían automáticamente en respuesta a los mensajes de ping, tal y como exige la especificación.

    Al igual que en el ejemplo del servidor anterior, sus clientes podrían perder la conexión sin saberlo. Es posible que desee agregar un oyente de ping en sus clientes toprevent que. Una implementación sencilla sería:

    const WebSocket = require('ws');function heartbeat() { clearTimeout(this.pingTimeout); // Use `WebSocket#terminate()`, which immediately destroys the connection, // instead of `WebSocket#close()`, which waits for the close timer. // Delay should be equal to the interval at which your server // sends out pings plus a conservative assumption of the latency. this.pingTimeout = setTimeout(() => { this.terminate(); }, 30000 + 1000);}const client = new WebSocket('wss://echo.websocket.org/');client.on('open', heartbeat);client.on('ping', heartbeat);client.on('close', function clear() { clearTimeout(this.pingTimeout);});

    ¿Cómo conectarse a través de un proxy?

    Usa una implementación personalizada http.Agent como https-proxy-agent osocks-proxy-agent.

    Changelog

    Estamos utilizando las versiones de GitHub para las entradas del registro de cambios.

    Licencia

    MIT

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *