7月 042014
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