Block Rockin’ Codes

back with another one of those block rockin' codes

Socket.IO v0.7 のロードマップと新機能

Node と言えば、Socket.IO といっても過言ではないほど、Socket.IO は Node にとって大きい存在です。


先の NodeConf で、この Socket.IO の作者 [twitter@rauchg] より、
Socket.IO v0.7 にむけたロードマップについての発表がありました。
新機能や API の改善等、重要な変更があるようなので一部を紹介したいと思います。


資料は以下。

Socket.IO(0.7)


(注 2011/05/31 現在 v0.7 はブランチで開発中であり、以下の紹介は上記資料をもとに書いているため、実行確認はしていません。
正式にリリースされた場合は、実装をもとに別途エントリを作成すると思うので、このエントリ自体は更新されない予定です。)

API の改善

サーバインスタンス

これまでは、ソケット通信を確立するためには、 http サーバインスタンスを渡す必要が有りましたが、今後は必要なくなります。

// Before
var io = require(‘socket.io’);
io.listen(http.createServer());

// After
var io = require(‘socket.io’);
io.listen(); // creates one for us

var io = require(‘socket.io’);
io.listen(8000); // creates one for us and listens on port 8000
オプション設定

これまでは全体で共通する設定を listen() 時に一つ適応できましたが、
今後は、 configure() メソッドを通じて listen() とは別に設定できます。
また configure() は第一引数に環境('production','development','test' etc) を設定でき、設定を切り替える事ができます。
(おそらく express との連携を視野に入れた対応)

// Before
var io = require(‘socket.io’);
io.listen(app, {
  tranportOptions: {}
});

// After
var io = require(‘socket.io’).listen();
io.configure(function () {
  io.set(‘polling duration’, 30);
});

io.configure(‘development’, function () {
  io.set(‘log level’, 3);
});

新機能

揮発性メッセージ

volatile.send() で、送信したら消える、揮発性のメーセージ送信をすることができます。

io.sockets.on(‘connection’, function (socket) {
  var t = setInterval(function () {
    getStock(‘APPL’, function (price) {
      socket.volatile.send(price); // send して終わり
    });
  }, 500);
  socket.on(‘disconnect’, function () {
    clearInterval(t);
  });
};
JSON

json.send() で送信データがJSONである事を明示できます。(シリアライズ不要)

io.sockets.on(‘connection’, function (socket) {
  socket.json.send(‘string’);
  socket.json.send(5);
  socket.json.send([
        {}
      , {}
  ]);
});
メッセージディスパッチャ

複数プロセスや分散環境での容易なスケールを目的とした機能も強化されるようです。
想像ですが、デフォルトではメモリとシングルプロセスになりますが、おそらく Redis 等との連携、マルチコア環境の適応を視野に入れているのかと。

まず環境をまたいだ変数共有のようなことができるようです(?)。

io.sockets.on(‘connection’, function (socket) {
  socket.get(‘nickname’, function (err, nick) {
   // セッションに対して設定した nickname の操作。
  });
});


非同期に接続中のクライアントを取得する場合は以下、環境をまたぎ、非同期に取得するようです。

io.sockets.on(‘connection’, function (socket) {
  io.sockets.clients(function (clients) {
    // 接続中のクライアントに対する操作
  });
});
送達確認

単純に send() メソッドにコールバックを追加することで、送達確認処理ができるようになります。

// server side
io.sockets.on(‘connection’, function (socket) {
  socket.send(‘bye’, function () {
    // 送達確認
  });
});

// client side
var socket = io.connect();
socket.send(‘hi’, function () {
  // 送達確認
});
// server side
io.sockets.on(‘connection’, function (socket) {
  io.on(‘nickname’, function (nick, fn) {
    checkAvailability(nick, fn);
  });
});

// client side
var socket = io.connect();
socket.emit(‘nickname’, prompt(‘Nickname’), 
function (res) {
  // if the function arity > 0, a callback is passed
  // to the event listener and the protocol signals
  // this is a Data ACK
});
名前空間

for() を使って、イベントごとの名前空間を指定できるようになります。
(無ければデフォルト)

// namespace “” (default)
io.sockets.on(‘connection’, function (socket) {
  io.on(‘nickname’, function (nick, fn) {
  });
});

// namespace “/news”
io.sockets
 .for(‘/news’)
 .on(‘connection’, function (socket) {
   io.on(‘item’, function (nick, fn) {
  });
});


for() ではなく、connect() を使ってソケット自体の名前空間で分ける事ができます。

var socket = io.connect(‘http://localhost/chat’)
var socket2 = io.connect(‘http://localhost/news’)

これにより、イベントやメッセージをチャネルごとに操作する事ができます。
(これまでやってきたチャネリングのハックが、実装に取り入れられる。便利!)

var news = io.sockets
 .for(‘/news’)
 .on(‘connection’, function (socket) {
   io.on(‘item’, function (nick, fn) {
   });
   news.emit(‘item’);
 });

var stream = io.sockets
 .for(‘/stream’)
 .on(‘connection’, function (socket) {
   io.on(‘item’, function (nick, fn) {
   });
   stream.emit(‘item’);
 });
ファーストクラスイベント
io.sockets.on(‘connection’, function (socket) { 
  io.on('chat message', function () {                             
  });
  io.on(‘nickname change’, function () {
  });
  io.sockets.emit('user connected', socket.id);
});

What’s coming

Express.IO

さらに Express との連携を強化し、Express のセッションと Socket.IO のセッションを共有する Express.IO なるモジュールが公開される予定です。
Express の作者 Tj と Socket.IO の作者 Guillermo Rauch は同じ LearnBoost で働いているため、彼らは手を組みやすい状況なのかも知れません。
目指すところは 「リアルタイム Web 界の Rails」とのこと、期待できますね!!

Other

他にも

  • CI とクラウド上での自動テスト
  • より高速な Flash フォールバック
  • Websocket の仕様変更への追従

などと、開発に意欲的な事が伺えます。

まとめ

Socket.IO 自体の完成度が上がる事で、リアルタイムアプリケーションを開発する際に出来ることもより増えると思います。
Guillermo Rauch さんはとてもストイックな開発者なので、今後のコミットにも期待したいと思います。
(日本に来ないかな ボソ)