5月末にでたSocket.IO 1.0に、socket.io-client-simpleを対応させた。

1.0対応は2週間ぐらい前にだいたいできてたんだけど、切断の検知と自動再接続する処理のあたりがうまくいかなくてリリースできてなかった。rubyのthreadの闇は深い。


うまく動くようになったのでどうぞ

% gem install socket.io-client-simple

変なところあったらgithubにissue立てたり、@shokaiにお知らせください


経緯


socket.io meetupに行ったら意識が高まったので、プレゼンとか聞きながらデバッグしてたらできてきて、意識高まりすぎて寿司とビールスルーして帰って電車の中でgem pushした。


socket.io 0.9 → 1.0の変更点メモ

ソースを読んだりして挙動を調べた。
研究室のwikiに書いたのメモのコピペで、たぶんgeta6とかnekobatoが書いてくれた情報も含まれる

クライアント作者としてはping-pongがサーバー→クライアントだったのがクライアント→サーバーになったおかげで切断検知しやすくなってうれしい感じした。


engine.io 1.1 -> 1.2に上がった

むしろこっちの変更の方が多いような気もする、あんまりちゃんと追えてない


初期化プロセスが変わった

最初に接続可能なプロトコル一覧を取るところから違う
xhr(comet?)で最初つないで、websocket使えるならwsに移行する

ということはrubyのsocket.ioクライアントはwebsocketだけのシンプル実装じゃだめ?
と思ったけど、いきなり/socket.io/?transport=websocket にwebsocket接続すればokだった。transportオプションがキモ

node.jsでもクラスターを取るとupgradeリクエストの後で400を返してしまう
クライアントの接続オプションにtransports: [‘websocket’, ‘polling’]を渡して以前と同じ挙動にできる
io.connect window.location.host, {transports: [‘websocket’, ‘polling’]}

failするユーザが高速につなげるようにするためにxhr-pollingを先行させている
開発するもののターゲットにレガシーブラウザが入っていなければwsを先行していいと思う

バージョンが混ざったらやばい

1.0のクライアントを0.9のサーバーに接続させようとするとサーバーで大量の”unhandled socket.io url”エラーが出る


通信データの格納方法が違う

server/client両方で環境変数 DEBUG=* を付けて通信させてみるとわかりやすい
頭に数字(制御コード)が付いたjsonをやりとりする。v0.9までは、”数字:::JSON” だった

“0” – 接続時にsession idなどを通知
0{"sid":"tOqSjGeyyhBo5x3vAAAA","upgrades":[],"pingInterval":25000,"pingTimeout":60000}

“41” – 切断
サーバーで明示的にsocket.disconnect()した時にクライアントに送られてくる
ただ “41” だけが送られてくる。


“42” – data
サーバーでemit(‘chat’, {msg: “hello”}, {foo: “bar”})した場合
42["chat",{"msg":"hello"},{"foo":"bar"}]
が送られてくる
送信時も42を付けて配列のJSONで送る


“1:6” – fast upgrade
はやくwebsocketにupgradeしろって指示をサーバーからクライアントに送る


“2” – ping
clientからserverへのping


“3” – pong
pingを受けての、serverからclientへのpong。これがすぐ返ってこなかったら、前段のnginxか何かにsocketがつながっているだけで、バックエンドのsocket.ioサーバーが息してないと判断できる


“2probe” – ajax ping
“3probe” – ajax pong

“5” – upgrade
ajax-pollingからwebsocketにupgradeする時にクライアントからサーバーに送る


heartbeatの手順が変わった

v0.9まで
サーバーが “2::” を送ってくるので、clientはすぐに”2::”を返す

v1.0以降
clientが”2″を送るとサーバーがすぐに”3″を返す
clientは接続してからすぐにサーバーに2を送らないと数秒で切られる

接続時の”0″で指定されたpingIntetrval(ミリ秒)毎に”2″を送ればok

この変更はすごく良い。普通TCP socketだとクライアントはなにかパケットを送ってみないと切断を検知できないので、今まで切断検知の為だけにnull送ってて無駄だった。

サーバーは何もしなくてももともと切断検知できるできる


io.configureが無くなった

log levelの設定はdebug npmを使う


io.connected

クライアントライブラリ側で接続状態を確認するio.socket.connectedがio.connectedに移動してた


シングルトン

client libは複数インスタンスを作っても、同じサーバーへの接続ならコネクションが共有される(単にキャッシュされた同じインスタンスが返ってくる)


client npmのIPアドレスが取得できない

socket.io-client npmからの接続のみ、サーバー側でクライアントのIPアドレスが取得できない
v0.9ではsocket.handshake.address.addressに入っていた
ブラウザjsからの場合、socket.handshake.address.address に入っている
client npmからだとaddressがnull


encoding

全体がUTF-8でエンコーディングされるようになった