Block Rockin’ Codes

back with another one of those block rockin' codes

node.jsのSocket IO-nodeでWebSocket

前回は、pywebsocketでのWebSocketを紹介しましたが、HTML5 hack-a-thonでは結局node.jsの実装である Socket IOとSocket IO-nodeを使いました。
こちらも備忘録。

node.js

node.jsはいわゆるサーバサイドJavaScriptの一つで、最近にわかに注目を集めてる(?)技術です。

主な特徴は

  • もちろん全てJSで書ける。
  • コアがGoogleのV8エンジンで速い
  • イベント駆動I/O


node.jsの概要自体は、こちらのPREZIを使ったプレゼンが簡潔で分かりやすいかと思います。

Introduction to node.js by Toshihiro Shimizu on Prezi


丁度今日、node.jsの48時間耐久Hack-a-thonが開催されていました。
その名も、Node.js Knockout。@さんも参加されてます。


Node.js Knockout | Nov 9-11th, 2013


node.jsについてはそのうちもう少し纏めた記事を書こうかなと思っています。
思った以上に手軽に色々出来るので、面白いです。


node.websocket.js

node.jsのWebSocket実装としては、ちょっと前までは以下のプロジェクトが良く紹介されていました。
今月のWeb+DB Press の「HTML5×CSS3」でもちらっと紹介されています。


guille/node.websocket.js · GitHub


とりあえずソースを取得し、runserver.js を起動したところ以下のようなエラーが出ました。

this.conn = new process.tcp.Connection();
                            ^
TypeError: Cannot read property 'Connection' of undefined


どうもこの実装は、node.jsのver 0.1.9以前でないと動かないようで、自分がビルドしているver 0.2.0ではサーバを起動することが出来ないようです。
(tcp.Connection()ではなくのAPIが変わってるみたいですね、今はnet.Stream() を使えばいいみたいです。)

プロジェクトのコミット自体が、2010/04/30で止まっていることを見ても、node.jsのバージョンアップに追従していないようです。

で、READE.mdには以下の記述。

Update: For a more complete and cross-browser/cross-platform solution, 
I recommend you check out Socket.IO and Socket.IO-node, which I'm actively maintaining.

今は、Socket.IOとSocket.IO-nodeをメインでメンテナンスしている。
そっちの方がより完璧なクロスブラウザ/クロスプラットフォームを実現しているので、そっちをお勧めするよ!

とのことです。

ということで、Socket.IOを使うことにします。

Socket.IO と Socket.IO-node

こちらも、node.websocket.jsと同じ作者の公開している実装です。
サーバ側の実装とクライアント側のライブラリの両方が提供されています。

Socket.IO-node

基本的にはWebSocketの実装というより、リアルタイム通信用のサーバ実装という位置づけのようです。
つまり、WebSocketが無いクライアントには、代替の手段を提供する実装になっているということで、以下をサポートしています。

    * WebSocket (with Flash policy support)
    * XHR Polling
    * XHR Multipart Streaming
    * Forever Iframe

node.jsはver0.1.102以上が必要とのことです。
また、クライアント側はSocket.IOを専用クライアントライブラリとして使います。
(普通のWebSocketオブジェクトを作成して試しましたが、通信は出来ませんでした。)

Socket.IO

Socket.IO-node専用のクライアントライブラリです。
これを使って実装すると、WebSocketの無いブラウザでもリアルタイム通信を実現することが出来ます。
READMEによるとサポートしているのは、

Supports

    * WebSocket
    * Adobe Flash Socket
    * ActiveX HTMLFile (IE)
    * XHR with multipart encoding
    * XHR with long-polling
    * JSONP polling (for cross-domain)

Tested on

    * Safari 4
    * Google Chrome 5
    * Internet Explorer 6
    * Internet Explorer 7
    * Internet Explorer 8
    * iPhone Safari
    * iPad Safari
    * Firefox 3
    * Firefox 4 (Minefield)

素晴らしいですね。
Draftの違いだけでなく、WebSocketの実装有無もカバーしてくれるので、WebSocketの無いブラウザでも同じコードで動かすことが出来るという点です。
多分現時点でここまで実用的なライブラリは中々無いと思います。


使い方

注意が必要なのは、二つが依存関係というか、二つペアで使うことを前提にしている点です。
なので、githubのソースも片方づつではなく、両方いっぺんに落として来て配備することが出来る様になっています。
Socket.IO-nodeの方に書かれてますが、以下の様に取得します。

git clone git://github.com/LearnBoost/Socket.IO-node.git socket.io-node --recursive
cd socket.io-node/example/
sudo node server.js


これで既にサンプルのchatアプリが動かせます。
それを動かしながら色々試してみたところ、前回の記事の様に、
サーバ:「来た物をそのまま返す」
クライアント:「サーバにただデータを投げて、ただ受け取る」
といった簡単な実装であれば、大まかにこんな感じで実装します。

//サーバ側の実装
var http = require('http'), 
    io = require('./path/to/socket.io'),

server = http.createServer(function(req, res){
    // サーバの設定
    res.writeHeader(200, {'Content-Type': 'text/html'});
    res.writeBody('<h1>Hello world</h1>');
    res.finish();
});

server.listen(8080); //リスニングするポート

var io = io.listen(server); //socketの取得

io.on('connection', function(client){
	//ユーザが接続して来たら実行される
	//接続時の初期化処理を書く

	client.on('message',function(message){
		//クライアントがメッセージを送って来たら実行される。
		//messageが送って来たデータ
		client.send(message); //送って来た本人だけに送る。
		client.broadcast(message); //送って来た人以外全員に送る。
	});

	client.on('disconnect', function(){
		//クライアントが切断したら実行される。
		client.broadcast(client.sessionId + ' disconnected' }); //他全員に切断した人のsessionIdを送る。
	});
});
//クライアント側の実装
//socket.io.jsファイルを読んでおく

//コネクションの確立
io.setPath('/path/to/socket.io/');
socket = new io.Socket('localhost',{port:8080});
socket.connect();

//データの送信
socket.send('data');

//データの受信
socket.on('message', function(data){
	//受信したら実行される
	//dataが受け取ったデータ
    console.log(data);
});


通信部分の実装自体は非常にシンプルですね。基本的にはこれだけです。
あとはこれどう使うかというアイデアだけです。


サンプルの中にあるChat等をいじりながら、色々試してみると良いと思います。

あと、今回のnode.js KOでも、リアルタイム系のアプリが多く有るようです。
おそらくSocket.IOを使った実装も多いはずなので、これらは多いに参考になると思います。
以下は、Hack-a-thonの作品と参加者の一覧。

Node.js Knockout | Nov 9-11th, 2013

メモ

node.jsは自分もまだ始めたばかりですが、今回使ってみて思ったところをメモしておきます。

  • node.jsは開発者がパフォーマンスをかなり気にしているだけあって、噂通りサクサク動いてる気がする。
  • イベント駆動IOの利点を生かして、こうしたソケット通信を用いたリアルタイムアプリケーションとnode.jsは相性が良いと言えそう。
  • Linux/Unixであれば導入する敷居はさほど高くない。
  • サーバ/クライアント共に同じ言語で書けるのは結構有り。
  • APIの実装も進み、フィレームワークもいくつか出ている。


node.js色々楽しみですね。