HTML5のWebsocketを使って同時接続数をサーバから送信する
HTML5のWebsocket(Node.js+Socket.IO)を使って、現在の同時接続数をサーバから送信するサンプルを作ってみました。
環境を作ったのは自分のPCのためリアルでお見せできないのが残念ですが、動画をキャプチャしたのでそちらでご確認ください。
1.サンプル動画
2つのブラウザからそれぞれ「http://127.0.0.1:8124」にアクセスして、そのページの同時接続数を各ブラウザに表示します。接続数の増減によって、ページに接続しているコネクションすべてに、サーバから情報を送信します。操作をしていないブラウザにも即時に接続数が反映されます。
非常にシンプルなものですが動いたときはちょっと感動しました。
2.サンプルコード
Node.jsとSocket.IOを使ったサンプルコードを掲載しておきます。
色々ネットを探しましたが(探しきれてないかもしれません)、Node.js+Socket.IOで動作するコードがみつからなかったので自作しました。Node.jsやSocket.IOに精通されている方にとっては当たり前のような実装かと思います。冗長な部分等ありましたらご指摘ください。
app.js(サーバ側のソース)
var app = require('express').createServer()
, io = require('socket.io').listen(app);
// カウンタ初期化
var count = 0;
app.listen(8124);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
// 接続時にカウンタのインクリメント
count++;
// ブロードキャストで送信
io.sockets.emit('user connected',count);
// 切断
socket.on('disconnect', function () {
// カウンタのデクリメント
count--;
// ブロードキャストで送信
io.sockets.emit('user disconnected',count);
});
});
index.html(クライアント側のソース)
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
jQuery(function(){
var socket = io.connect('http://localhost');
// 接続時の動作
socket.on('user connected', function (data) {
jQuery('span').html(data);
});
// 切断時の動作
socket.on('user disconnected', function (data) {
jQuery('span').html(data);
});
});
</script>
<div>このページにアクセスしているのは<span></span>人です。</div>
サンプルコードの配置や起動方法については、Windows限定ですが「Windows+Node.js+Socket.IO」を参照してください。
また、このコードを実行する前に、上記記事の最後に掲載している「npm install socket.io express」を実行してください。
3.クライアントへの送信方法
サーバからブロードキャストで送信するには次のように記述するようです。赤色はイベント名で、任意の文字列を記述します。
io.sockets.emit('user connected', count);
受け取るクライアントでは、サーバ側のemit()の第1引数(赤色のイベント名)を必ず指定します。ここが一致していないと受信できません。第2引数のデータは引数として扱えます。
socket.on('user connected', function (data) {
// ...
});
サンプルコードはブロードキャストで行ってますが、次のように記述すれば送信先を変更できるようです。
// 自分以外の全員に送る
socket.broadcast.emit('user connected',count);
// 自分だけに送る
socket.emit('user connected', count);
4.参考サイト
参考サイトは下記です。ありがとうございました。
Windows+Node.js+Socket.IO
Windowsを使ってNode.js+Socket.IOを試してみました。
マシンはWindows VISTAですが、Windows 7でも同じだと思います。以前はCygwinでコンパイルをしないといけなかったようですが、現在はWindows用のexeファイルが提供されていて、かなり簡単に動かすことができるようになっています。
1.Node.jsとは
Node.jsは、サーバサイドJavaScriptの実装の1つで、グーグルが開発したV8 JavaScriptエンジン上で実行します。要するにサーバ側の処理をJavaScriptで書くことができます。
サーバサイドJavaScriptには「CommonJS」という仕様が策定されており、Node.jsはCommonJSに準拠して開発されています。2012/01/10追記:独自仕様もあるようです。
Node.jsの特徴として、非同期処理を行うための「イベントループ」と呼ばれる技術を用います。「イベントループ」というのは「C10K問題(クライアント1万台問題)」で有名になった技術で、大量のクライアントからのリクエストを処理するためのアーキテクチャです。
Node.jsはシングルスレッドなので、イベントループ処理はノンブロッキングI/O(データ送受信(I/O)の完了を待たずに、他の処理を開始する処理方式)で実現します。
つまり、すべての処理をノンブロッキングI/Oにしておかないと、イベントループ処理が止まってしまいます。例えば他の言語でノンブロッキングI/Oを実現するにあたってライブラリを利用する場合、ライブラリでブロックしていないことが要件となりますが、JavaScriptはそもそもブロッキングI/Oをもっていないので、相性が良い(そういうことを心配する必要がない)らしいです。
2.Node.jsのインストール
Node.js公式サイトにある「DOWNLOAD」をクリック。
「Windows Installer」をクリック。
ダウンロードしたファイルを実行します。「Next」をクリックすればすぐにインストールが開始します。
インストール中です。
完了しました。めちゃくちゃあっさりしています。
Node.jsは「C:¥Program Files¥nodejs」というフォルダにインストールされます。実行ファイルは「C:¥Program Files¥nodejs¥node.exe」です。「npm」という、Node.js用のパッケージマネージャも一緒にインストールされており(ネットで調べると以前は別にインストールする必要があったようですが不要)、同じフォルダにある「npm.cmd」が該当します。
3.Node.jsの動作確認
Nodeはコマンドプロンプトから操作します。ということで、コマンドプロンプトを起動します。
まずバージョンを表示する「node --version」を入力してみます。インストール時にパスは通っているはずなので、どのフォルダからでも起動できると思います。
バージョンが表示されました。「node --help」を入力すれば利用可能なオプションが表示されます。
パスが通っているかどうかは、「コンピュータ」→右クリックで「プロパティ」→「システムの詳細設定」→「詳細設定」タブ→「環境変数」→「システム環境変数」の「Path」を選択して「編集」をクリックすれば分かります。
Node.jsはV8エンジン上で動いているので、通常の処理もできるようです(というかNode.jsはネットワーク処理に特化したライブラリらしいです)。単に「node」と入力すると「>」というプロンプトが表示されるので、計算などが行えるようです。
こちらを終了させる場合はCtrl-cを2回行います。
4.ブラウザからNode.jsにアクセスする
ブラウザからNode.jsにアクセスして何かを表示するにはnode起動時にクライアントを通信を行うためのJavaScriptファイルを指定します。クライアントから任意のURL(後述)にアクセスすると、このJavaScriptファイルが動作するという仕組みです。
Node.jsの公式サイトにあるサンプルファイルを用いて、ブラウザからアクセスして「Hello World!」を表示させてみます。次のファイルをexample.jsというファイル名でnodejsフォルダ直下に作成します。
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');
コマンドプロンプトから「node example.js」を入力します。
「Server running at http://127.0.0.1:8124/」は、console.log()の内容なので、これが表示されていれば正常に動作しています。この状態でブラウザから「http://127.0.0.1:8124/」にアクセスしてみます。
おぉ!表示されました。
5.Socket.IOのインストール
Socket.IOはHTML5のWebSocket(クライアント・サーバの双方向通信)を実現するために必要なライブラリのようです。WebSocketで双方向通信を確認したかったのですが、この記事では簡単なサンプル動作にとどまってます。
ネットで調べたところ、Googleの「Socket.IO」というのがみつかったのでこれを利用してみます。「Socket.IO」の「How to use」をクリック。
ここに以下のようなnpmコマンドが載っていました。
npm install socket.io
ということで、コマンドプロンプトからこのコマンドを実行します。
インストールされたようです。
6.Socket.IOのサンプル作成(Node HTTP server)
「How to use」のページに掲載されているサンプルを動かしてみます。
サーバ側のファイルです。app.jsというファイル名でとりあえずnodejsフォルダに作成します。
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
クライアントが読み込むファイルをindex.htmlというファイル名で、app.jsと同じフォルダに配置します。script要素でsocket.io.jsをインクルードしています。このパスはこのままでOKです。
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
コマンドプロンプトから「node app.js」を実行してみましたが、「Error: listen EADDRINUSE」というエラーが発生しました。
これは、app.jsで指定しているリスンポートが正しくないためです(ポート80はPC上でXAMPPを起動しているためと思われます)。ということで、app.jsのポートを8124に変更します。
app.listen(8124);
これで再度起動します。多分うまく動作していると思います。
このサンプルは、ブラウザからアクセスすると真っ白な画面になります。
ソースコードはindex.htmlの内容が表示されているので、正常に動作しているようです。
表示されたソースコード上のsocket.io.jsをクリックしたところ、こちらも正常に表示されました。
とりあえずここまでです。「How to use」のページには他にもサンプルがあるので色々試してみるとよいでしょう。サンプルによっては、次のコマンドを実行する必要があるようです。
npm install socket.io express