読者です 読者をやめる 読者になる 読者になる

console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

Socket.IOのその他できること

Node.js Socket.IO

前回の最小構成でSocket.IOを試すサンプル - console.lealog();の続きです。
最小構成でそれらしさを体験した後は、その他にどんなものが使えるのかを。

参考:LearnBoost/socket.io · GitHub

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('/')ってなってるとのこと。
クライアント側できっちりパス切らないとハマります。

参考:Socket.IOを用いたマウスカーソルの共有 - 自分の感受性くらい

各ページというあたりがキモ。
全ページに同じ記述書いてあれ・・?ってなるのは俺だけで良いです。

どっちかというとルーティングのが面倒くさい。

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()のセットを使う気がする。

その他

他にもまだ機能がある

参考:LearnBoost/socket.io · GitHub

今回触れてないことも少しだけこの記事には書いてあります。
個人的にあんまり使わなさそう・・って思ったのでスルーしました。

send()とemit()

時折これらがごっちゃになってたけど解決!

参考:socket.ioの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'});


うーん、いろいろ作れそうやけど、この分野はテストするの大変そうやね。