1. ホーム
  2. node.js

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

2023-10-17 20:09:10

質問

私は 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"が必要で、別のファイルで io.sockets.on() のコールバックとして使用する匿名関数が必要で、さらにこれらのファイルの両方を正常に含めるために 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 を追加するために console.log('User connected'); を追加したが、これは表示されない。

あるファイルに Socket.IO があり、別のファイルにファイル サーバーがあり、それでも両方が正しく動作することを期待するにはどうしたらよいでしょうか。

どのように解決するのですか?

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)