HTML5でサーバプッシュ(Node.jsとWebSocket)

HTML5 Advent Calendar2011の6日目。

私がHTML5の中で最も注目しているWebSocketについて書きます。
今更説明するまでもないのですが、WebSocketはHTML5で実装されたサーバプッシュを
「簡単に」実現させることができます。

サーバプッシュと言うくらいなので、当然サーバ側の仕組みが必要で、
WebSocketサーバを実現するライブラリが世の中には既にかなりありますが、
なんといってもNode.jsを使ったNode WebSocket Serverがお手軽で、
クライアントサイドと同じJavaScriptで書けるのが素敵。


とまぁ、能書きはいいので、簡単なサンプルを。
Node.jsのインストールはこちら辺りを参考にどぞ。
Node WebSocket Serevrはnpmコマンドでインストールします。

#> npm install websocket-server

これでカレントディレクトリのnode_modules/以下にインストールされる。

ではまずクライアント側から。

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" />
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<title>ニュース速報</title>
<script type="text/javascript">
window.onload = function() {
	//WebSocketオープン
	socket = new WebSocket("ws://192.168.12.50:10080");
	socket.onmessage = function(event) {
		document.getElementById('news').innerHTML = event.data;
	}
}
</script>
</head>
<body>
ニュース受信中:<div id="news"></div>
</body>
</html>

IPアドレスは適当に自分の環境に合わせて書き換えてください。
またポート番号は10080にしていますが、これも自分の環境に合わせて。
当然WebSocketサーバ側でListenするポート番号と一致している必要があります。
このサンプルはサーバプッシュされてきた文字列を単に表示させているだけ。

次にサーバ側。

先ほどのnode_modules/ というディレクトリと同階層にこのjsファイルを設置します。
newsServer.js

var sys = require("util");
var fs = require("fs");
var ws = require("websocket-server");
var server = ws.createServer();

server.addListener("connection", function(connection){
	var client_id = connection.id;
	sys.log("Connected->"+client_id);
	readFile();

	fs.watchFile('./news.dat',readFile);
});

function readFile(curr,prev) {
	fs.readFile('./news.dat','UTF-8', function(err,data) {
		sys.log("news->"+data);
		server.broadcast(data);	
	});
}

server.listen(10080);

このjsファイルと同じ階層にnews.datというファイルを作成し、
このファイル内にテキストで適当にニュースなりメッセージなり書いておきます。

#> echo "This is first news." > news.dat

準備ができたらWebSocketサーバを起動しておきます。コマンドラインから、

#> node newsServer.js
node newsServer.js

で起動。


ブラウザでindex.htmlを開きます。
WebSocketに対応するブラウザはwikipedia:WebSocketを参照。
ただMacChromeだとうまく動かない。Win版Chromeは不明。
Opera11なら(設定すれば)動作可。SafariはWinでもMacでもOK。
iPhone/iPadでも可。Androidは不可。

ブラウザで開くと、サーバ側のコンソールには、

5 Dec 23:44:47 - Connected->3942536650
5 Dec 23:44:57 - news->This is first news.

なんて出ます。This is first news.ってのがnews.datの中身。
クライアント側のブラウザには

ニュース受信中:
This is first news.

となってるはず。

で、news.datを書き換える。

echo "second news" > news.dat

するとこの内容がクライアント側にほぼ瞬時に伝わることが分かるでしょう。

まぁこれはあくまでもサンプルなので何の実用性もないけども、例えばnews.datではなく
ニュースの内容をDBに登録しておき、最新ニュースがDBに登録されたら
クライアントにサーバプッシュしたり、野球やサッカーの試合速報、チャット、
対戦型ゲーム、オークションサイトでの応札状況、株価、ショッピングサイトでのタイムセール、etc・・・
将来的には緊急地震速報をサーバプッシュで配信するのもありかも(※今は安定性や対応ブラウザが少ない)。

注:ここから宣伝。

今月末に、小生が執筆したHTML5を使ったスマートフォン向けWebアプリ制作の本が
秀和システムから発刊されることになりました。
その中でこのNode.js+Web Socket Serverを使ったサンプルアプリを紹介していますので、
興味のある方はよろしければどうぞ。

注:ここまで宣伝乙。


と、まぁ応用範囲はアイディア次第で無限なWebSocketに、今後も期待大、というお話でした。