MessagePack on socket.ioでのバイナリ転送案
前提
- socket.io 1.3.5
socket.ioのroomかnamespaceか悩んだ末、問題はバイナリの転送だけなので、MessagePackなどを使えば良いのではないかと考えました。プロトコルも素直になるので。
MessagePack:JavaScript向けのライブラリではいずれもバイナリを文字列としてデコードする(MessagePackの仕様上は文字列とバイナリデータを区別しない)ので、バイナリを扱おうとすると処理系によってデータを変更されてしまう可能性があることがわかりました。
BSON:配列を使うとデータサイズが大きくなる(配列のインデックスを添え時にしたmapとして扱っている)という欠点があります(あとJavaScriptに依存しすぎた型も多いですが使わなければ良い)。配列バンバン使うのでまずいです。
Base64:C++からJavaScriptにバイナリデータを渡すときにBase64エンコーディングをかける方法もありますが、単純にサイズが増えます。 (´・ω・`)ウ~ンMessagePackのライブラリを改造してUint8Arrayを戻す形にすれば良いかな?と調べたら改造済みのものがあるようです。
追記
などと調べていたら、socket.ioの1.0以降ではバイナリ転送(Blog, Uint8Array)を含むオブジェクトの転送が可能だそうです。
参考
socket.ioでサーバからクライアントへバイナリデータを送る際の送信元
前提
- socket.io 1.3.5
socket.ioのroomにはsocket.io自体にクライアントがどのroomに対してメッセージを送ったか判別する手段がない。つまり、1ユーザが同時に複数のroomに所属する場合、どのroomにメッセージを送るかは送信メッセージ上で組み込む必要がある。JavaScriptで解析が面倒なバイナリデータを転送する場合はroom機能を使わないか、バイナリをbase64エンコードなどする必要がありそう(JSONにバイナリデータを格納した場合、バイナリセーフである確証が得られなかったため)。
もう一つ、namespaceという機能があり、この場合、どのnamespace宛にデータを送信したかsocket.ioで判定可能になる。ただし、namespaceから特定クライアントだけを切断したり、namespace自体を解散する公式なAPIが今のところ無いようだ。(roomは切断APIがあり、すべてのクライアントが切断した場合roomが解散される) 試した挙句、機能自体はnamespaceで作り、切断の機構を自作するしかなさそう。
参考
socket.ioのon('connect')とon('connection')の2通りの書き方があった
前提
- socket.io 1.3.5
socket.ioの接続イベントはon('connection', <接続時に呼ばれる関数>)とマニュアルに書いているけど、プログラム中ではon('connect', <接続時に呼ばれる関数>)と実装されている。バグかドキュメントのミスじゃないかと調べたら、なんと両方動いた。マニュアルにないけど、of(, <接続時に呼ばれる関数>)でも同じ動作をする。このときはon('connect')が内部で呼ばれてた。
JavaScriptのlocation.hostが返す値にはポート番号が含まれる場合がある
前提
- JavaScript @ Opera 28
- socket.io 1.3.5
ブラウザのJavaScript、location.hostはlocalhost:8080のようにポート番号が付記される。ただしポート番号が80の場合はlocalhostだけとなる。サンプルを実行してlocalhostだからといって、ポート番号を結合するコード(location.host + ':8080'
)を書くとlocalhost:8080:8080となって接続できない、、、とおもいきや、socket.ioのnamespaceに接続する場合は何もエラーを吐かずに動かないだけ、原因究明にえらい時間を使った。