Jxck です。 KOBA からのでいいかなと思ったんですが、 一応書いたので置いておきます。
最初は正直何がしたいのかよくわかりませんでした。 ただ、話を聞いてる感じだとやろうとしていることに対して、 やってることが過度に複雑なだけのようだったので。 (同じサーバなのに、わざわざ自分自身にソケットを経由するとか) KOBA のも参考にしつつこんな感じかと。 (コメントを読んで下さい。) https://gist.github.com/4624554 拙作ですが、翻訳してるのでこちらもご参考まで。 http://jxck.github.com/socket.io/#how-to-use https://github.com/Jxck/socket.io/wiki/Rooms Jxck On Thursday, January 24, 2013 11:18:19 PM UTC+9, matton wrote: > > KOBA789 さん ご丁寧にありがとうございます。 > > まず、socket.ioの標準機能を再度確認致します。 > 自身に接続してチャンネルに join している部分を見直します。 > 変数の件、知りませんでした。ありがとうございます。 > また、typo と思われたのは"_c"付きの部分のことだと思います。 > ”socket_c ” とか "join_c"です。 > URL引数にてデータを受け取る為、データ受信の回数分http.createServerが行われるのでその都度ではなく、 > 自身に接続してチャンネルに joinは一度だけとする為の部分です。 > それで最適な方法が思いつかず、外側のスコープの変数による状態の受け渡しを行ってしまった次第です。 > > 明日になりますが、ソース見直し致します。 > > よろしくお願いします。 > > > 2013年1月24日木曜日 22時33分49秒 UTC+9 KOBA789: >> >> KOBA789 です。 >> >> なるほど、問題点の本質がわかりました。 >> まず、Socket.IO >> の仕様をよく知った方がよいかと思います。標準機能を適切に活用することで解決できる問題は多くあります。自身に接続してチャンネルに >> join している点に関してはこれで解決できます。 >> また、現状の外側のスコープの変数による状態の受け渡しでは、ロックが必要になってしまいますし、クロージャを使える JavaScript >> を用いた実装としては素直ではありません。はっきり言って悪い実装ですから避けなければなりません。なお、変数に無駄なスコープを持たせないことはバグの発見の容易さや、バグの回避につながります。 >> >> >> 最後に重箱の隅をつつくようで申し訳ありませんが、変数の初期化に空文字列を乱用するのは避けたほうがよいでしょう。型に合わせた初期化をすることで、VM >> はメモリ確保に関して最適化をします。ですから、不適切な型による初期化はパフォーマンス劣化につながります。 >> 以上の点を踏まえてソースを書き直すと以下のようにできるかと思います。ただ、typo >> と考えられるものなどがいくつかあり、ソースの真意が読めない部分が多いため、どうしても多くを憶測で書いてしまいました。挙動が異なってしまっていたら申し訳ありません。 >> >> >> >> ====================================================================== >> >> var http = require("http"); >> var url = require("url"); >> >> function start(route,handle){ >> function onRequest(request,response){ >> var queryData = url.parse(request.url, true).query; >> var url_parts = url.parse(request.url,true); >> var query = url.parse(request.url, true).query; >> var pathname = url.parse(request.url).pathname; >> >> serversocket2("Appname",query); >> request.setEncoding("utf8"); >> >> request.addListener("end",function(){ >> route(handle,pathname,response); >> }); >> } >> >> var server = http.createServer(onRequest).listen(8080); >> //console.log("Serevr has sterted."); >> >> // socket.io >> var io = require('socket.io').listen(server); >> >> >> var archiveMessages = {}; >> var channels = ['Appname']; >> >> var appname = io.of('/appname'); >> appname.on('connection', function(socket){ >> console.log('connected: %s', socket.id); >> >> // push available channel list >> socket.emit('available_channel', channels); >> >> socket.on('join', function(value){ >> console.log('%s joined channel: %s', socket.id, value.channelId); >> >> socket.join(value.channelId); >> socket.set('channel_id', value.channelId); >> }); >> >> socket.on('post', function(message){ >> socket.get('channel_id', function(err, channelId){ >> console.log(' %s says<%s channel>: %s', socket.id, channelId, >> message); >> >> }); >> }); >> >> socket.on('disconnect', function(){ >> console.log('%s disconnected', socket.id); >> socket.get('channel_id', function(channelId){ >> socket.leave(channelId); >> }); >> }); >> >> }); >> >> function serversocket2(channelId,data){ >> appname.in(channelId).emit('user:message', data); >> } >> }; >> >> exports.start = start; >> >> 2013年1月24日 20:28 matton <[email protected]>: >> > KOBA789さん返信ありがとうございます。 >> > >> > はじめにnode初めて間もない為、ソースが汚く申し訳ございません。 >> > >> > >> setTimeoutを使用している理由は"serversocket1"にてクライアント(自分)→サーバ(自分)にjoinを行っているのですが、サーバ側の処理(socket.join)が終わる前に"serversocket2"が動くと"socket_c"が空の状態となる為、setTimeoutを用いています。 >> >> >> > ※"socket_c"は"socket.join"にてセットしています。 >> > >> > http.createServerの処理とsocket.io<http://http.xn--createserversocket-7h4qxd8192fh5mg.io>間でコールバックをネストさせる方法はわかりませんでした。 >> > >> >> > >> > お手数ですが、アドバイスよろしくお願いします。 >> > >> > >> > 2013年1月24日木曜日 19時36分23秒 UTC+9 KOBA789: >> >> >> >> KOBA789 です。 >> >> >> >> 指摘したい点はたくさんありますが、まず1点だけ失礼します。 >> >> なぜ、わざわざ setTimeout による時間差によって実行順序を指定するということをしているのでしょうか。 >> >> >> >> >> 素直に考えて、コールバックをネストさせることで対応するのが最善だと思うのですが、そうしなかった理由を教えていただきたいです。その理由知ることでより踏み込んだアドバイスができると考えています。 >> >> >> >> >> >> 2013年1月24日 11:03 matton <[email protected]>: >> >> > お世話になります。 松尾と申します。 >> >> > >> >> > node.jsにて下記の様な仕組みを作成しております。 >> >> > >> >> > 現在、バッチプログラム(vs.net C#)にてDB監視を行い、結果をクライアントに通知する仕組みを作成しています。 >> >> > 監視バッチ→node.js→ios/android >> >> > >> >> > >> として、node.js→ios/androidはリアルタイム通知の為、soket-ioを使用しています。(※ちなみに監視バッチ→node.jsはwebsocketが使用できない為、URLにてデータを渡しています。 >> http://xxx?1=a&2=B) >> >> > node.js内でアクセスされたURL引数をJSONに変換してクライアントへsocket-ioにて一斉配信しています。 >> >> > >> >> > >> >> > >> とりあえず動いてはいるのですが、URLで受け取ったデータをsocket-ioにて配信する際、一度、自分自身のsocket-ioにconnectしてsocketにセットしています。 >> >> >> >> > >> >> > >> connectが非同期となる為setTimeoutを利用している為、サーバの負荷次第ではconnect処理(serversocket1)を配信処理(serversocket2)が追い越してしまうと考えています。 >> >> >> >> > >> >> > 何か良い制御方法は無いのでしょうか? >> >> > >> >> > よろしくお願いします。 >> >> > >> >> > 環境 >> >> > windows2003 sp2 >> >> > node v0.8.17 >> >> > >> >> > >> >> > メイン部分のソースです。 >> >> > >> >> > >> ------------------------------------------------------------------------------------------- >> >> >> >> > var http = require("http"); >> >> > var url = require("url"); >> >> > >> >> > var socketval = 0; >> >> > >> >> > >> >> > function start(route,handle){ >> >> > var query = ""; >> >> > function onRequest(request,response){ >> >> > var queryData = url.parse(request.url, true).query; >> >> > var url_parts = url.parse(request.url,true); >> >> > query = url.parse(request.url, true).query; >> >> > var pathname = url.parse(request.url).pathname; >> >> > if(socketval===0){ >> >> > >> setTimeout(function(){serversocket1("Appname",query)},1); >> >> > }; >> >> > >> >> > >> setTimeout(function(){serversocket2("Appname",query)},1000); >> >> > request.setEncoding("utf8"); >> >> > >> >> > request.addListener("end",function(){ >> >> > route(handle,pathname,response); >> >> > }); >> >> > } >> >> > >> >> > var server = http.createServer(onRequest).listen(8080); >> >> > //console.log("Serevr has sterted."); >> >> > >> >> > // socket.io >> >> > var io = require('socket.io').listen(server); >> >> > >> >> > >> >> > var archiveMessages = {}; >> >> > var channels = ['Appname']; >> >> > >> >> > var appname = io.of('/appname'); >> >> > var socket = ""; >> >> > var socket_c = ""; >> >> > appname.on('connection', function(socketin){ >> >> > console.log('connected: %s', socket.id); >> >> > socket = socketin; >> >> > >> >> > // push available channel list >> >> > socket.emit('available_channel', channels); >> >> > >> >> > socket.on('join', function(value){ >> >> > console.log('%s joined channel: %s', socket.id, >> >> > value.channelId); >> >> > >> >> > socket.join(value.channelId); >> >> > }); >> >> > socket.on('join_c', function(value){ >> >> > console.log('clientjoin %s joined channel: %s', >> socket.id, >> >> > value.channelId); >> >> > >> >> > socket.join(value.channelId); >> >> > socket_c = socket; >> >> > socketval=1; >> >> > }); >> >> > >> >> > socket.on('post', function(message){ >> >> > socket.get('channel_id', function(err, channelId){ >> >> > console.log(' %s says<%s channel>: %s', socket.id, >> >> > channelId, message); >> >> > >> >> > }); >> >> > }); >> >> > >> >> > socket.on('disconnect', function(){ >> >> > console.log('%s disconnected', socket.id); >> >> > socket.get('channel_id', function(channelId){ >> >> > socket.leave(channelId); >> >> > }); >> >> > }); >> >> > >> >> > }); >> >> > >> >> > var io_c = require('socket.io').client; >> >> > var appname_c = ""; >> >> > function serversocket1(channelId,data){ >> >> > var appname_c_1 = io_c.connect('http://localhost:8080'); >> >> > appname_c = appname_c_1.of('/appname'); >> >> > >> >> > appname_c.emit('join_c', { >> >> > channelId: 'Appname' >> >> > }); >> >> > >> >> > } >> >> > function serversocket2(channelId,data){ >> >> > socket_c.set('channel_id', channelId, function(){ >> >> > socket_c.emit('posted', data); >> >> > socket_c.broadcast.to(channelId).emit('user:message', >> data); >> >> > }); >> >> > } >> >> > }; >> >> > >> >> > exports.start = start; >> >> > >> >> > >> ------------------------------------------------------------------------------------------------ >> >> >> >> > >> >> > >> >> > >> >> > -- >> >> > >> >> > >> >> > >> > >> > -- >> > >> > >> > >> > --
