socket.ioの習作解説その弐

<!-- ブラウザ側 -->
        <script src='/socket.io/socket.io.js'></script>
        <script src='/javascripts/jquery-2.0.3.min.js'></script>

今回サンプルのHTMLにはサーバ側で動くコードは一切なく、すべてブラウザ上で実行されます。その中でsocket.ioの賢い仕組みとしてはこちら。/socket.io/socket.io.jsを要求してダウンロードします。一緒に並べているjQueryのコードの要求とはちょっと違って、socket.io.jsは下記サーバコードがサービスします。jquery-2.0.3.min.jsは先に作ったexpressでの静的WEBサーバがサービスしてくれています。

//サーバ側
var chatroom = require('socket.io').listen(server).of('/chatroom');

require('socket.io').listen()の引数に、別に作ったhttp.Serverを渡せば通常のHTTPサーバの陰に隠れてWebSocketのサーバが上がります。その後のof()はこのWebSocketに名前空間をつける機能で、まあ普通の神経ならこうするんだろうと。グローバルな名前空間でサービス立ち上げてると、後にサービス仕様の拡張で別サービスを同居させたくなったときに書き直しが発生するし。もちろん上記ではワンライナーで書いちゃってるので、下記のように書き換えないといけないけど。

//サーバ側
var io = require('socket.io').listen(server);
var chatroom = io.of('/chatroom');
var viproom = io.of('/viproom');

脱線しましたが、ここまでやるとブラウザへsocket.io.jsがダウンロードされます。このダウンロードしたコードを使って通信始めるところがHTMLのscriptタグ内の以下。

<!-- ブラウザ側 -->
            $(function() {
                var chatroom = io.connect('/chatroom');
                //(省略)
            });

jQueryのReadyハンドラで、io.connect()するだけ。引数には名前空間を指定します。ここで世のドキュメントの多くは「http://localhost/chatroom」みたいにホストも書いちゃってるけど、私はそう書いちゃいけないように思うんだよなあ。ブラウザのセキュリティモデル上、スクリプトダウンロード元としか通信しちゃダメだよね。この辺は理由が謎。localhostで動作確認すると問題なく上記の「/chatroom」で動きます。グローバル空間は「/」でよいです。
世のWebSocketの読み物など参考にすると、一発目のhttpでWebSocket接続を要求して双方コンディション整えばつなぎっぱなし、昔の言葉で言えばcometとかいうようなこと、になると。socket.ioはこのへんの接続を整えるところはこれだけのコードに機能集約されて楽チンです。ブラウザ種別の挙動の違いも吸収しているのだとも。素敵です。