ローカル環境のnodeプログラムからsocket.ioに繋ぎたい場合、やっぱりnode-websocket-clientとかでゴニョゴニョするしかないのかな? socket.io-clientをrequireするだけで使えたら素敵なのだけど
var io = require('socket.io'); var http = require('http'); var WebSocket = require('websocket-client').WebSocket; var parser = io.parser; function HTTPClient (host, port) { this.host = host; this.port = port; this.agent = new http.Agent({ host: host, port: port }); }; HTTPClient.prototype = { get: function (path, callback) { var buf = ''; var req = http.request({ host: this.host, port: this.port, path: path, }, function (res) { res.on('data', function (chunk) { buf += chunk; }); res.on('end', function () { callback(null, res, buf); }); }); req.on('error', function (err) { console.log('error'); callback(err); }); req.end(); }, handshake: function (callback) { this.get('/socket.io/' + io.protocol, function (err, res, data) { if (err) { throw err; } callback(data.split(':')[0]); }); } }; function WSClient (host, port, sid) { this.sid = sid; this.port = port; WebSocket.call( this, 'ws://' + host + ':' + port + '/socket.io/' + io.protocol + '/websocket/' + sid ); }; WSClient.prototype = { __proto__: WebSocket.prototype, emit: function (name) { var args = arguments; if (name === 'message' || name === 'data') { args[1] = parser.decodePacket(args[1].toString()); } return WebSocket.prototype.emit.apply(this, arguments); } }; function websocket (host, port, callback) { var client = new HTTPClient(host, port); client.handshake(function (sid) { callback(new WSClient(host, port, sid)); }); } websocket('127.0.0.1', '3000', function (socket) { socket.on('open', function () { console.log('open!'); }); socket.on('message', function (msg) { console.log(msg); }); });
こんなかんじで作っておくと、
var io = require('socket.io').listen(3000); io.sockets.on('connection', function (socket) { setInterval(function () { console.log('emit'); io.sockets.emit('hoge', 'fuga'); }, 1000); });
みたいなサーバに対し繋ぐとmessageを受け取れているのが確認できる。
$ node client.js open! { type: 'connect', endpoint: '', qs: '' } { type: 'event', endpoint: '', name: 'hoge', args: [ 'fuga' ] } { type: 'event', endpoint: '', name: 'hoge', args: [ 'fuga' ] } { type: 'event', endpoint: '', name: 'hoge', args: [ 'fuga' ] } { type: 'event', endpoint: '', name: 'hoge', args: [ 'fuga' ] } { type: 'event', endpoint: '', name: 'hoge', args: [ 'fuga' ] }
hostとportを正しく指定すれば、外部サーバに対してでも(v0.7系で動作していて、WebSocket接続がサポートされていれば)繋げられるはず。
宿題
@sugyan redisまたはzeromqを間に挟むと簡単に実現。次のでごく簡単なコード送ります。io.sockets.on('connection', ....の中にredisやzeromqに聞き耳を立てるようにしておくと、どこからでもsocket使えますよ。
2011-08-04 12:11:15 via web to @sugyan
@sugyan redis_pub.publish(channel, JSON.stringify(message)); redis_sub.on('message, function(message){io.sockets.emit('message', message)});
2011-08-04 12:11:37 via web to @sugyan
基本的に同一マシン内でサーバ/クライアント両方立ち上げているときにRedisを仲介して通知しあう、という方法なのだという理解ですが…