Versão npmBuildWindows x86 BuildCoverage Status

ws é um simples de usar, rápida, e exaustivamente testada a implementação de cliente e servidor WebSocket.

Passa a suite de teste Autobahn bastante extensa: servidor,cliente.

Nota: Este módulo não funciona no navegador. O cliente nos documentos é referência a um back end com o papel de um cliente na WebSocketcommunication. Os clientes do browser devem usar o nativoWebSocketobject. Para que o mesmo código funcione perfeitamente no Node.js e no browser, pode utilizar um dos muitos invólucros disponíveis em npm, comoisomorphic-ws.

Tabela de conteúdos

  • Suporte de protocolo
  • Instalar
      li>Opt->in para desempenho e conformidade com as especificações
  • /li>

  • API docs
  • Compressão WebSocket
  • Exemplos de utilização
    • Enviar e receber dados de texto
    • Enviar binário data
    • Servidor simples

  • Servidor HTTP/S externoServidor HTTP/S múltiplo partilhando um único servidor HTTP/S

  • Autenticação do cliente
  • li>Servidor broadcastli>echo.websocket.org demoli>Utilizar o Nó.js streams API

  • Outros exemplos
  • FAQ
    • Como obter o endereço IP do cliente?
    • Como detectar e fechar ligações quebradas?
    • Como ligar através de um proxy?
  • Changelog
  • Licença
  • Suporte de protocolo

    • HyBi drafts 07-12 (Use a opção protocolVersion: 8)
    • HyBi drafts 13-17 (Current default, alternativamente opçãoprotocolVersion: 13)

    Instalação

    npm install ws

    Opt-in para desempenho e conformidade com as especificações

    Existem 2 módulos opcionais que podem ser instalados juntamente com o wsmodule. Estes módulos são suplementos binários que melhoram determinadas operações. Estão disponíveis binários pré-construídos para as plataformas mais populares, pelo que não é necessário ter desnecessariamente um compilador C++ instalado na sua máquina.

    • npm install --save-optional bufferutil: Permite realizar eficientemente operações como mascarar e desmascarar a carga útil de dados dos WebSocketframes.
    • npm install --save-optional utf-8-validate: Permite verificar eficazmente se a amessage contém UTF-8 válida, conforme requerido pelo spec.

    API docs

    See /doc/ws.md para documentação tipo Node.js- das classes ws e funções de utilidade.

    compressão WebSocket

    ws suporta a extensão permessage-deflate que permite ao cliente e ao servidor negociar um algoritmo de compressão e os seus parâmetros, e depois aplicá-lo selectivamente às cargas úteis de dados de cada mensagem WebSocket.

    A extensão é desactivada por defeito no servidor e activada por defeito no cliente. Adiciona uma sobrecarga significativa em termos de desempenho e consumo de memória, pelo que sugerimos que só seja activada se for realmente necessária.

    Nota que o Node.js tem uma variedade de problemas com compressão de alto desempenho, onde o aumento da concorrência, especialmente no Linux, pode levar a uma fragmentação catastrófica e a um desempenho lento. Se pretende utilizar o Node.js/zlib em produção, vale a pena criar um representante de teste da sua carga de trabalho e garantir que o Node.js/zlib irá lidar com ele com desempenho aceitável e utilização de memória.

    A afinação do permessage-deflate pode ser feita através das opções definidas abaixo. O canal também utiliza zlibDeflateOptions e zlibInflateOptions, que é passado directamente para a criação de fluxos de deflacionar/inflacionar em bruto.

    Ver os documentos para mais opções.

    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. }});

    O cliente só utilizará a extensão se esta for suportada e activada no servidor. Para desactivar sempre a extensão no cliente definir operMessageDeflate opção para false.

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

    Exemplos de utilização

    Envio e recepção de dados 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);});

    Envio de dados binários

    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 simples

    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);

    Vários servidores que partilham um ú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);

    Autenticação do cliente

    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);

    Também ver o exemplo fornecido usando express-session.

    Transmissão do servidor

    Um cliente WebSocket transmitindo para todos os outros clientes WebSocket ligados, incluindo a si próprio.

    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); } }); });});

    Um cliente WebSocket transmitindo para todos os outros clientes WebSocket ligados, excluindo-se a si próprio.

    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); } }); });});

    echo.websocket.org demo

    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);});

    Usar o Nó.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);

    Outros exemplos

    Para um exemplo completo com um cliente browser a comunicar com um servidor ws, ver a pasta de exemplos.

    Outra, ver os casos de teste.

    FAQ

    Como obter o endereço IP do cliente?

    O endereço IP remoto pode ser obtido a partir da tomada bruta.

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

    Quando o servidor corre atrás de um proxy como NGINX, o padrão de facto é para usar o X-Forwarded-For cabeçalho.

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

    Como detectar e fechar ligações quebradas?

    Por vezes a ligação entre o servidor e o cliente pode ser interrompida de forma a manter tanto o servidor como o cliente inconscientes do estado quebrado da ligação (por exemplo, ao puxar o cabo).

    Nestes casos, as mensagens ping podem ser utilizadas como um meio de verificar se o ponto remoto ainda responde.

    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);});

    As mensagens ping são automaticamente enviadas em resposta às mensagens ping, conforme requerido pelas especificações.

    Apenas como o exemplo do servidor acima dos seus clientes pode também perder a ligação sem o saber. Poderá querer adicionar um ouvinte de ping aos seus clientes para evitar que isso aconteça. Uma implementação simples seria:

    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);});

    Como ligar através de um proxy?

    Utilizar um personalizado http.Agent implementação como https-proxy-agent ou socks-proxy-agent.

    Changelog

    Usamos os lançamentos GitHub para entradas no changelog.

    Licença

    MIT

    Deixe uma resposta

    O seu endereço de email não será publicado. Campos obrigatórios marcados com *