前回の最小構成でSocket.IOを試すサンプル - console.lealog();の続きです。
最小構成でそれらしさを体験した後は、その他にどんなものが使えるのかを。
set/get
接続してるクライアントに対して、データをset/getする機能。
ソースは必要なところだけ抜粋です。
Server side
io.sockets.on('connection', function (socket) { // [2]送信されたnicknameをset socket.on('set nickname', function (name) { socket.set('nickname', name); }); // [4]送られるたびに・・ socket.on('msg', function (data) { // [5]nicknameをgetすることが可能! socket.get('nickname', function (err, name) { console.log(name + ' says: ' + data); }); }); });
Client side
// [1]最初に接続したとき、nicknameを送信 socket.on('connect', function () { socket.emit('set nickname', prompt('What is your nickname?')); }); // [3]そうすると以後なにか送るたびに socket.emit('msg', 'Sending something...')
[5]で変数に入れちゃわずコールバックに渡してるのは、それがNodeっぽい使い方だからってやつかな。
この程度の軽い処理なら大丈夫そうやけど、お作法としてやらない感じ。
セットするのも1つのオブジェクトにしちゃって、プロパティで追加していく方がよさそう。
broadcast
待ってました!
今までも散々使ったけどw
Server side
io.sockets.on('connection', function (socket) { socket.on('message', function (data) { socket.broadcast.emit('msg', data); }); });
Client side
socket.emit('message', 'Msg1');
これぞリアルタイムWebな感が出て楽しいですねw
ちなみにbroadcastされるのは、自分以外のソケットに対してです。
名前空間とか部屋とか
of('/hoge')
// Server side var io = require('socket.io').listen(80); io.of('/speakers').on('connection', function(socket) { socket.on('location', function(data) { data.id = socket.id; socket.broadcast.emit('location', data); }); }); io.of('/sponsors').on('connection', function(socket) { socket.on('location', function(data) { data.id = socket.id; socket.broadcast.emit('location', data); }); }); /* of使わない時はsockets io.sockets.on('connection', function(socket) { socket.on('location', function(data) { data.id = socket.id; socket.broadcast.emit('location', data); }); }); */
// Client side var socket = io.connect('http://219.94.254.115/speakers'), // .... /* // もしくは var socket = io.connect('http://219.94.254.115/sponsors'), // .... */
1つのソケット=単一のプロセスでもって、処理系を分けたい場合に使うのがof('/hoge')らしい。
普段のofをつけないやりとりは、暗黙の内にof('/')ってなってるとのこと。
クライアント側できっちりパス切らないとハマります。
各ページというあたりがキモ。
全ページに同じ記述書いてあれ・・?ってなるのは俺だけで良いです。
どっちかというとルーティングのが面倒くさい。
JoinとLeave
これで楽々ルーム機能つきチャットが。
// Server side var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) { socket.join('justin bieber fans'); socket.broadcast.to('justin bieber fans').emit('new fan'); io.sockets.in('rammstein fans').emit('new non-fan'); });
join('hoge')に対応してleave('hoge')も使えます。
クライアント側はいつもと同じように受けるだけでOK。
たぶんこのサンプル、記述を間違えてるような?(他にもちょいちょい間違いあったし。
このサンプルにあるように、文字列で識別させようとしても上手くいかなかったのよね・・。
代わりに最初に紹介したset/getでサーバー側で保持してるオブジェクトを参照させれば上手くいきました。
joinとleaveはソケットは子供(各クライアントを表す)のメソッドやけど、toとinは親(io自身)のメソッドらしい。
var socket = io.sockets.on('connection', function(client) { client.on('init', function(req) { client.set('room', req.room); client.set('name', req.name); socket.to(req.room).emit('System', '[' + req.name + '] has come.'); client.emit('System', 'Join [' + req.room + '] as [' + req.name + ']. Enjoy!'); client.join(req.room); }); client.on('leave', function() { var obj = {}; getRoomAndNameObj(client, obj); if (obj.name) { socket.to(obj.room).emit('System', '[' + obj.name + '] has left..'); } client.leave(obj.room); }); });
broadcast.emit()よりも、こっちのto().emit()のセットを使う気がする。
その他
他にもまだ機能がある
今回触れてないことも少しだけこの記事には書いてあります。
個人的にあんまり使わなさそう・・って思ったのでスルーしました。
send()とemit()
時折これらがごっちゃになってたけど解決!
なるほどねー、send(hoge)とemit('message', hoge)は一緒なのね。
- connected
- message
- disconnected
は接続しただけで自動的に受けれる(サーバー側にemitのロジック書かなくても)・・と。
json形式でやり取りもできる
↑と内容が若干かぶるような気もしないでもないけど。
- チャットみたいに送受信するメッセージに色んなパターンがあったり、あれこれしたい場合には、emitでやる。
- 単にデータのやり取りをしたいだけなら、sendでシンプルに。
そう理解しておこう・・。
// チャットとか、いろいろやるパターン socket.emit('myFirstEvent', 'Hihi!'); socket.emit('mySecondEvent', 'How r u?'); socket.broadcast.emit('globalEvent', 'Hello everyone.'); // RESTのAPIのエンドポイントみたくシンプルに使うパターン socket.json.send({obj: 'Hello!'}); socket.broadcast.json.send({obj: 'Hello!', time: '20121006'});
うーん、いろいろ作れそうやけど、この分野はテストするの大変そうやね。