web-dev-qa-db-ja.com

node.jsでファイルサーバーとsocket.ioロジックを分離する

私はnode.jsを初めて使用しますが、プロジェクトのサイズが大きくなると、プロジェクトが複数のファイルに分割されるのが非常に複雑になることがわかりました。以前には、マルチプレイヤーHTML5ゲームのファイルサーバーとSocket.IOサーバーの両方として機能する1つの大きなファイルがありました。ファイルサーバー、socket.IOロジック(ネットワークから情報を読み取り、タイムスタンプ付きのバッファーに書き込み、他のすべてのプレーヤーに送信する)、およびゲームロジックを分離するのが理想的です。

Socket.ioの最初の例を使用して問題を説明すると、通常は2つのファイルがあります。 _app.js_はサーバーであり、_index.html_はクライアントに送信されます。

app.js:

_var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
_

index.html:

_<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>
_

ファイルサーバーとゲームサーバーのロジックを分離するには、1つのファイルで定義された関数「handler」が必要になります。これらのファイルの両方を正常に含める3番目のファイル。今のところ、私は次を試しました:

start.js:

_var fileserver = require('./fileserver.js').start()
  , gameserver = require('./gameserver.js').start(fileserver);
_

fileserver.js:

_var app = require('http').createServer(handler),
    fs = require('fs');

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

module.exports = {
    start: function() {
        app.listen(80);
        return app;
    }
}
_

ゲームサーバー:

_var io = require('socket.io');

function handler(socket) {
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', function (data) {
        console.log(data);
    });
}

module.exports = {

    start: function(fileserver) {       
        io.listen(fileserver).on('connection', handler);
    }

}
_

データは送信されませんが、これは機能しているようです(静的コンテンツが適切に提供され、クライアント接続時にコンソールがSocket.IOとのハンドシェイクを明確に表示します)。 socket.emit()とsocket.on()が実際に呼び出されることはないかのようです。 _gameserver.js_のhandler()を変更してconsole.log('User connected');を追加しましたが、これは表示されません。

1つのファイルにSocket.IOを、別のファイルにファイルサーバーを配置し、それでも両方が正しく動作することを期待するにはどうすればよいですか?

68
stevendesu

Socket.io 0.8では、io.sockets.on('...')を使用してイベントをアタッチする必要があります。名前空間を使用していない限り、sockets部分が欠落しているようです:

io.listen(fileserver).sockets.on('connection', handler)

そのようにチェーンすることは避けたほうがよいでしょう(後でioオブジェクトを使用したいかもしれません)。私が今これをしている方法:

// sockets.js
var socketio = require('socket.io')

module.exports.listen = function(app){
    io = socketio.listen(app)

    users = io.of('/users')
    users.on('connection', function(socket){
        socket.on ...
    })

    return io
}

サーバーappを作成した後:

// main.js
var io = require('./lib/sockets').listen(app)
82
Ricardo Tomasi

私はこのようなことをします。

app.js

var app = require('http').createServer(handler),
    sockets = require('./sockets'),
    fs = require('fs');

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

sockets.startSocketServer(app);
app.listen(80);

およびsockets.js

var socketio = require('socket.io'),
        io, clients = {};

module.exports = {

        startSocketServer: function (app) {
                io = socketio.listen(app);

                // configure
                io.configure('development', function () {
                        //io.set('transports', ['websocket', 'xhr-polling']);
                        //io.enable('log');
                });

                io.configure('production', function () {
                        io.enable('browser client minification');  // send minified client
                        io.enable('browser client etag');          // apply etag caching logic based on version number
                        io.set('log level', 1);                    // reduce logging
                        io.set('transports', [                     // enable all transports (optional if you want flashsocket)
                            'websocket'
                          , 'flashsocket'
                          , 'htmlfile'
                          , 'xhr-polling'
                          , 'jsonp-polling'
                        ]);
                });
                //

                io.sockets.on('connection', function (socket) {
                        console.log("new connection: " + socket.id);

                        socket.on('disconnect', function () {
                                console.log("device disconnected");

                        });

                        socket.on('connect_device', function (data, fn) {
                                console.log("data from connected device: " + data);
                                for (var col in data) {
                                        console.log(col + " => " + data[col]);
                                }


                        });
                });
        }
};

古いコードの一部をコピーして貼り付けました-socket.ioの最後のバージョンで何が変わったのか実際にはわかりませんが、これは実際のコードよりも構造に関するものです。

そして、私はあなたの目的のために3つではなく2つのファイルのみを使用します。それをさらに分割することを考えると、おそらく別のルートのために他の1つのファイルを...

お役に立てれば。

5
pkyeck

私もこれにひびがありました、そして、結果にかなり満足しています。ソースコードについては、 https://github.com/hackify/hackify-server をご覧ください。

1