前回まででNUCのハードを組み立てて、OSやJavaScript実行環境Node.jsなど、基本的なソフトのインストールを準備しました。
今回はいよいよWebSocketサーバーを立ち上げ、アプリを動かします。
WebSocketサーバーといっても、今回はWebSocketサーバーそのものを作るわけではありません。サーバーにはNode.jsのnpmパッケージからwsというWebSocket用モジュールを利用します。
このモジュールはあの有名なSocket.IOで、WebSocketのコアの部分にも使われている高速なWebSocketサーバーを持っています。アイディア次第で、たとえば、チャットサーバーにでも、ゲームデータサーバーにでも、あるいは、ニュース配信サーバーにでも何にでも使えます。
「WebSocket」自体は双方向通信のプロトコルとAPIというだけですので、その使い方次第で用途は無数に考えられるわけです。
今回作るもの
今回は、NUCを使って、とりあえずWebSocketサーバーを立ち上げてみようという短期連載ですので、その雰囲気がわかる程度の簡単なものでやってみます。
恐縮ですが拙著「Node.jsプログラミングガイド」のサンプルの中から、WebSocketを使ったリアルタイムチャートを作ってみます。ここでのWebSocketサーバーは、チャートへデータを連続的にプッシュし続ける機能を担います。
まず最初に前回もチラ見した、仕上がりをもう一度見てみましょう。
下の赤い「Play」ボタンをクリックすると動きます。
(invalid jsdo.it code)
上記チャートはccchartですが、チャートが変化し続けるためのデータがサーバー側からリアルタイムにプッシュされ続けています。Ajaxなどのように、ブラウザ側からユーザーがリクエストする必要はありません。
このケースでは、すべての接続しているブラウザのチャートへデータが自動的にプッシュされ続けます。
この仕組みを使えば、たとえば、社内の毎時変化するデータなどを関係者全員がリアルタイムに閲覧するといったシステムを作ることも簡単です。
ちなみに参考までですが、ccchartのメリットはCanvasベースなので高速でSVGよりもプラットフォーム依存が少ないことと、インターネットにつながっている必要もないのでイントラネットでも使えることなどでしょうか。
(※今回は解説できませんが、もし、このサンプルが動かない環境なら、ポートを80や443などにする必要があるかもしれません。ただし、Linuxでは80などのwell-known ポートは、今回のようなユーザー権限ではなくroot権限で起動する必要があり、セキュアにすることも考慮すると別途少し手間がかかります)
では、これをNUC内に置いてみます。
ソースを取得する
まず、今回使うソースを手に入れます。「Node.jsプログラミングガイド」のサンプルページ
1-Basic Knowledge 基礎知識 から
02-wsserver2にある2つのファイル
chart.htm
wsserver.js
をコピーします。クライアント側のHTMLとJavaScript、つまりchart.htmのコードは、下記にもありますが jsdo.itのサンプルからもご確認いただけます。
アプリ用のディレクトリを用意する
ファイルを作る場所はお好みですが、今回は、ユーザー名を仮にhogeとして、ホームディレクトリ(/home/hoge) 配下へ前回作っておいた公開用ディレクトリ /home/hoge/public_html を利用して、Apacheで公開してみます。
作成するディレクトリツリーは、次のようになります。
/home/hoge
├──public_html/
│ └─mychart
│ └─chart.htm
└──wsserver.js
まず、ホームディレクトリのpublic_html下にchart.htmを置くためのディレクトリmychartを作ります。
1 2 3 |
cd /home/hoge/public_html mkdir mychart cd mychart |
mychartディレクトリができたら、そこへ chart.htm をFTPでアップロードしておきましょう。wsserver.jsは、/home/hoge直下へ置きます。
次に、そのひとつ上の非公開ディレクトリ /home/hoge/ 内に node_modules というディレクトリを作ります。
1 2 |
cd /home/hoge mkdir node_modules |
これは、Nodeのモジュールが格納される場所で、ディレクトリ/home/hoge配下でインストールするローカルなモジュールは、(インストールコマンドnpmの引数-gを指定しなければ) ここに入ります。
また、wsserver.jsはサーバー側ですので一般的には、公開ディレクトリpublic_htmlではなく非公開な場所(今回は/home/hoge直下)へアップロードします。
WebSocket用モジュールをインストール
では次にNodeのWebSocket用モジュールwsを入れてみます。これには高速なWebSocketサーバーとクライアントが同梱されています。
では入れてみましょう。
1 |
npm i ws |
これだけです。(npm install wsと同じ意味です) では、node_modules下に本当に入ったのかlsコマンドで見てみましょう。
1 |
ls -l /home/tato/node_modules |
すると、下記のように表示されるのでwsが入っていることがわかります。
total 4
drwxrwxr-x 11 hoge hoge 4096 1月 15 18:36 ws
作成されたディレクトリツリーは、次のようになっているはずです。
/home/hoge
├──public_html/
│ └─mychart
│ └─chart.htm
├──wsserver.js
└──node_modules/ ←追加された
└─ ws/
これで、設置完了です。簡単でしょう? でも、ここでhttp://192.168.1.180/~hoge/chart.htmをブラウザで開いても動きません。
サーバーが起動していないからです。
では、動かしましょう。
WebSocketサーバーを起動する
以下のおまじないを打ち込みます。ホームディレクトリ/home/hoge/下のwsserver.jsをNodeで動かすという意味です。
1 |
node ~/wsserver.js |
node /home/hoge/wsserver.jsでも同じ意味になります。
もし、ここでエラーが出なければ、同一ネットワーク内の他のパソコンのブラウザで http://192.168.1.180/~hoge/chart.htm を開いてみてください。
動いてますね。さらに、別のパソコンで開いても見ることができます。
永続化
「node ~/wsserver.js」でサーバーを起動しましたが、このままでは、sshの接続を切るとサーバーが止まってしまいます。
そこで、永続化やNUCの再起動時も自動で立ち上がるための仕掛けが必要です。
永続化には、foreverというモジュールがよく使われます。再起動時の自動起動は、/etc/init.dへの登録などの方法がありますが、残念ながら紙面の都合で書ききれませんので、不明な方はこれらのキーワードで調べてみてください。
この連載のアクセスが多ければ続きを書けるかもしれません(笑)。 でも、それを待つよりも、もしわからなければ、自分で調べると身につきますよ。
サーバー側のコード
参考までにサーバー側ソースは次のようなものです。
手短に言うと、指定したポートへクライアントから接続があると、0.3秒ごとに生成しているデータをすべてのクライアントへプッシュしています。詳しくはソースとコメントをご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
//WebSocket Serverモジュールを読み込む var WsServer = require('ws').Server; //port: 3001でリッスンするサーバーを作成する var ws = new WsServer({ port: 3001 }); //タイマーID var tid; broadCast();//データ配信開始 function broadCast(){ //0.3秒ごとにデータを送信する tid = setInterval (function(){ //データを作る var dataAry = mkData(); //すべてのクライアントへ送信する ws.clients.forEach(function(client) { client.send(JSON.stringify(dataAry)); }); }, 300); } // 送信用ランダムデータを作成する(実際には必要なデータを与える) function mkData(){ //送信データ形式の雛形 var data = [ ["時間"], ["s2"], ["s3"] ]; //時間の文字列を作成する var now = new Date(); var H = now.getHours(); var M = now.getMinutes(); var S = now.getSeconds(); H = (H < 10)?'0'+H:H; M = (M < 10)?'0'+M:M; S = (S < 10)?'0'+S:S; //送信データを作成する data[0]=H +':' + M +':' + S; data[1]=Math.floor(Math.random(10) * 96 ); data[2]=32 + Math.floor(Math.random(10) * 18); return data; } |
クライアント側のコード
ccchart自体の使い方は今回は紙面の都合で触れませんが、ポイントは、ccchartのwsメソッドの引数でサーバー側のIPアドレスとポートを指定している部分です。そこから流れてきたデータを自動的にconfigで指定した形式にチャート化します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<script src="http://ccchart.com/js/ccchart.js" charset="utf-8"></script> <canvas id="hoge"></canvas> <script> var chartdata = { //チャートの設定 "config": { "title": "WebSocket TEST", "subTitle": "列データをリアルタイム受信描画 受信パターンはoneColAtATime", "type": "bezi2",//チャートタイプベジェ曲線 他にline, barなど "width" : 465,//幅 "lineWidth": 2,//線の太さ "minY": 0,//最小Y値 "xScaleSkip": 5,//垂直目盛のスキップ "colorSet": //カラーセット ["#DDA0DD","#3CB000"] }, //データの雛形 "data": [ ["時間"], ["s2"], ["s3"] ] }; ccchart .init('hoge', chartdata) //要素hogeへチャートデータchartdataを出力する .ws('ws://192.168.1.180:3001') //このURLをサーバー側のIPとポートに合わせる .on('message', ccchart.wscase.oneColAtATime);//このパターンで受信する // oneColAtATimeは、WebSocketの受信パターン関数 // 一度に1列ずつ [["2013"],[435],[600]] といった配列で届く場合用 // 参照: http://ccchart.org/test/someCols/test-2.htm </script> |
最後に
以上、駆け足で手のひらサイズのWebSocketサーバーを組み立ててみました。
ほんの10年ほど前までは、一般的には、手のひらサイズのサーバーなどほとんど考えることもありませんでしたが、今、それはすでに目の前にあります。
一方に社外クラウドサーバーを利用する大きな流れがありますが、同時に、目の前には、わずか数万円でモニタの裏にも貼れるような小さな内製サーバーを作れるという選択肢も生まれたわけです。
エクセルを使って仕事の効率を上げるように、ちょっとした業務には、どこにでも持っていける小さな内製サーバーを使って効率を上げるということも可能な時代になりつつあります。
多くの業務と製品がネットワーク経由のサービスと無縁ではなくなりつつある今、たとえば、機動性の高いサービスをより現場に近い場所で、NUCを使って次々と立ち上げるといった未来が、文字通り、今、私たちの手の上にあります。
NUC 自体の用途は限定されていません。さて、どんな未来を作りましょうか?
<関連レポート>
NUCで手のひらサイズの格安WebSocketサーバーを立ててみた(ハード組立編)を読む⇒
NUCで手のひらサイズの格安WebSocketサーバーを立ててみた(OSインストール編)を読む⇒