ファイナンス、情報通信技術のスキル・アグリゲーション・サイト

' . iseeit.jp 情報通信技術 . '

Node.js で Secure WebSocket(https.js + express.js + ws.js)

Node.js で WebSocket サーバーを構築するためのパッケージはいくつかありますが、このページでは、WebSocket パッケージのひとつ ws.js を利用した例を取り上げます。さらに、WebSocket(ws://)と Secure WebSocket(wss://)の接続に、それぞれ http.js と https.js も使用します。なお、今回の内容に、ウェブフレームワークの express.js は必須ではありませんが、組み入れています。

ws - npm Usage examples には、いくつものコード例かあり、そのままでも、あるいは組み合わせると、大抵のことはできそうです。今回は、External HTTP/S server の例と Server broadcast の例をベースにして Secure WebSocket サーバーを、そして、Sending and receiving text data の例からテスト用クライアントを作成します。

パッケージのインストールと Secure WebSocket サーバー側コード例

まずは、かんたんに Node.js とパッケージ管理の npm のインストールをみていきます。

たとえば、Ubuntu 16.04 LTS 標準のままの apt もしくは apt-get でインストールすると、古いバージョンがインストールされます。



$ sudo apt install nodejs

このことをふまえながら Google 検索してみていくと、Ubuntu では、多くの方が n というバージョン管理パッケージを利用しているようです。

npm も含めてインストールは簡単に、という思いもあり、以下のページの手順でインストールを進めました。

https://nodejs.org/en/download/package-manager

LTS( long-term support )版の場合。



$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt install -y nodejs

最新版の場合。



$ curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
$ sudo apt install -y nodejs

この手順では、Node.js とともに npm もインストールされます。また、nodejs コマンドのほか、node コマンドでも使えるようになっています。

次に、npm を利用して、ws.js、express.js、https.js http.js をインストールします。



$ npm install ws express https http

さて、今回使用した SSL/TLS 証明書は、プライベート認証局(CA)を作成して、プライベート SSL/TLS 証明書を発行したものです。この手順については、プライベート認証局でプライベート SSL/TLS 証明書を発行する も参考にしてください。

今回作成した Secure WebSocket サーバーのコード例です。



var WebSocket = require('ws');
var fs = require('fs');
var http = require('http');
var https = require('https');
var express = require('express');
var app = express();
 
app.use(express.static(__dirname + '/'));

var server = http.createServer(app);
var wss = new WebSocket.Server({server:server});

var  _ca_certs = '/etc/ssl/certs/ca.crt';
var  _certfile = '/etc/ssl/certs/client.crt';
var  _keyfile = '/etc/ssl/certs/client.key';
  
var key = fs.readFileSync(_keyfile);
var cert = fs.readFileSync(_certfile);
var ca = fs.readFileSync(_ca_certs);

var options = {
  key: key,
  cert: cert,
  ca: ca
};

var server_secure = https.createServer(options, app);

var wss_secure = new WebSocket.Server({server:server_secure});

// すべての接続へブロードキャスト
wss.broadcast = function broadcast(data) {
  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
};
wss_secure.broadcast = function broadcast(data) {
  wss_secure.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
};

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);
      }
    });
  });
  wss_secure.broadcast(data);
});
wss_secure.on('connection', function connection(ws) {
  ws.on('message', function incoming(data) {
    // ほかの接続へブロードキャスト
    wss_secure.clients.forEach(function each(client) {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(data);
      }
    });
  });
  wss.broadcast(data);
});

server.listen(8080);
server_secure.listen(8081);

サーバー側コード例のベースとなる Usage examples

External HTTP/S server



const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');

const server = new 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);

Server broadcast



const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

// Broadcast to all.
wss.broadcast = function broadcast(data) {
  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
};

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(data) {
    // Broadcast to everyone else.
    wss.clients.forEach(function each(client) {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(data);
      }
    });
  });
});

テスト用クライアントのコード例

Sending and receiving text data のコード例です。



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

ws:// のテスト用クライアントは、ホスト名とポート、パスをサーバー側にあわせます。

次に、wss:// のテスト用クライアントコード例です。



process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const WebSocket = require('ws');
 
const ws = new WebSocket('wss://www.host.com:8081');

ws.on('open', function open() {
  ws.send('something');
});
 
ws.on('message', function incoming(data) {
  console.log(data);
});

なお、コードの先頭行は、プライベート認証局の CA 証明書を使用した場合の、次のエラーを回避するものです。プライベート認証局の CA 証明書は、Node.js 向けに信頼されたルート証明機関の証明書ではないことによります。



Error: self signed certificate in certificate chain

または、一時的にプライベート認証局の CA 証明書を設定する環境変数を、実行コマンドの前に加える方法があります。



$ NODE_EXTRA_CA_CERTS='/etc/ssl/ca.crt' node wssclient.js

ファイナンシャル・プランニング
6つの係数

終価係数 : 元本を一定期間一定利率で複利運用したとき、将来いくら になるかを計算するときに利用します。

現価係数 : 将来の一定期間後に目標のお金を得るために、現在いくら の元本で複利運用を開始すればよいかを計算するときに利用します。

年金終価係数 : 一定期間一定利率で毎年一定金額を複利運用で 積み立て たとき、将来いくら になるかを計算するときに利用します。

年金現価係数 : 元本を一定利率で複利運用しながら、毎年一定金額を一定期間 取り崩し ていくとき、現在いくら の元本で複利運用を開始すればよいかを計算するときに利用します。

減債基金係数 : 将来の一定期間後に目標のお金を得るために、一定利率で一定金額を複利運用で 積み立て るとき、毎年いくら ずつ積み立てればよいかを計算するときに利用します。

資本回収係数 : 元本を一定利率で複利運用しながら、毎年一定金額を一定期間 取り崩し ていくとき、毎年いくら ずつ受け取りができるかを計算するときに利用します。

積み立て&取り崩しモデルプラン

積立金額→年金額の計算 : 年金終価係数、終価係数、資本回収係数を利用して、複利運用で積み立てた資金から、将来取り崩すことのできる年金額を計算します。

年金額→積立金額の計算 : 年金現価係数、現価係数、減債基金係数を利用して、複利運用で将来の年金プランに必要な資金の積立金額を計算します。