バージョン npmBuildWindows x86 BuildCoverage Status

wsは、シンプルで使いやすい。

ws は、使いやすく、非常に高速で、徹底的にテストされた WebSocket クライアントとサーバーの実装です。

非常に広範な Autobahn テストスイート (サーバー、クライアント) をパスしています。

注意: このモジュールはブラウザでは動作しません。 ドキュメントにあるクライアントとは、WebSocket 通信におけるクライアントの役割を持つバックエンドのことを指しています。 ブラウザのクライアントは、ネイティブのWebSocketオブジェクトを使用する必要があります。 同じコードをNode.jsとブラウザでシームレスに動作させるには、npmで提供されているisomorphic-wsのような多くのラッパーを使用することができます。

目次

  • プロトコルのサポート
  • インストール
    • パフォーマンスと仕様準拠のための最適な
  • APIドキュメント
  • WebSocketの圧縮
  • 使用例
    • テキストデータの送受信
    • バイナリデータの送受信
    • i データ

  • 単純なサーバー
  • 外部のHTTP/Sサーバー
  • 単一のHTTP/Sサーバーを共有する複数のサーバー
  • クライアントの認証
  • サーバーのブロードキャスト
  • echo.websocket.orgのデモ
  • Use the Node.js streams API
  • その他の例
  • FAQ
    • クライアントのIPアドレスを取得するには?
    • 壊れた接続を検出して閉じるには?
    • プロキシ経由で接続するには?
  • Changelog
  • License
  • プロトコルのサポート

    • HyBi drafts 07-12 (オプションprotocolVersion: 8を使用)
    • HyBi drafts 13-17 (現在のデフォルト。 代わりにオプションprotocolVersion: 13

    インストール

    npm install ws

    パフォーマンスと仕様準拠のためのオプトイン

    wsmodule と一緒にインストールできるオプションモジュールが 2 つあります。

    • npm install --save-optional bufferutil C++ コンパイラをインストールする必要はありません。
    • npm install --save-optional utf-8-validate:WebSocket フレームのデータ ペイロードのマスキングやアンマスキングなどの操作を効率的に実行できます。

    API docs

    /doc/ws.md WSクラスやユーティリティー関数のNode.jsライクなドキュメントについては/doc/ws.mdを参照してください。

    WebSocket compression

    ws は permessage-deflate extension をサポートしており、クライアントとサーバーが圧縮アルゴリズムとそのパラメーターをネゴシエートし、各 WebSocket メッセージのデータ ペイロードに選択的に適用することができます。

    この拡張機能は、サーバーではデフォルトで無効になっており、クライアントではデフォルトで有効になっていますが、パフォーマンスとメモリ消費の点でかなりのオーバーヘッドが発生するため、本当に必要な場合にのみ有効にすることをお勧めします。

    なお、Node.jsには高性能圧縮に関するさまざまな問題があり、特にLinuxでは同時実行性が高まるとメモリの断片化が発生し、パフォーマンスが低下する可能性があります。

    permessage-deflateのチューニングは、以下のオプションを使って行うことができます。

    また、zlibDeflateOptionszlibInflateOptionsを使用して、生のdeflate/inflateストリームの作成に直接渡すこともできます。

    その他のオプションについては、ドキュメントを参照してください。

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

    クライアントは、拡張機能がサーバーでサポートされ、有効になっている場合にのみ使用します。 クライアントで拡張機能を常に無効にするには、perMessageDeflatefalseに設定します。

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

    使用例

    テキストデータの送受信

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

    バイナリデータの送受信

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

    簡易サーバ

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

    外部の 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);

    単一の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);

    クライアントの認証

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

    また、express-sessionを使用した提供されている例も参照してください。

    サーバー ブロードキャスト

    クライアントの WebSocket は、自分自身を含む、接続されているすべての WebSocket クライアントにブロードキャストしています。

    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 デモ

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

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

    その他の例

    ブラウザクライアントがwsサーバーと通信する完全な例については、examplesフォルダを参照してください

    その他にはテストケースを参照してください。

    リモートの IP アドレスは生のソケットから取得できます。

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

    サーバーが NGINX のようなプロキシの後ろで動作している場合は、X-Forwarded-For ヘッダーを使用するのがデファクトスタンダードです。

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

    壊れた接続を検出して閉じるには?

    サーバーとクライアントの間のリンクは、サーバーとクライアントの両方が接続の切断状態に気づかないような方法で中断されることがあります (例: コードを引っ張ったとき)。

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

    Pongメッセージは、仕様で要求されているように、pingメッセージに応じて自動的に送信されます。

    上記のサーバーの例のように、クライアントは知らないうちに接続を失っているかもしれません。 それを防ぐために、クライアントに ping リスナーを追加するとよいでしょう。

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

    プロキシ経由で接続するには

    https-proxy-agentやsocks-proxy-agentのようなカスタムhttp.Agent実装を使用します。

    Changelog

    変更履歴はGitHubのリリースを使用しています。

    License

    MIT

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です