web-dev-qa-db-fra.com

Séparation du serveur de fichiers et de la logique socket.io dans node.js

Je suis assez nouveau sur node.js et j'ai trouvé qu'il était assez compliqué de séparer un projet en plusieurs fichiers à mesure que le projet grandit. J'avais auparavant un gros fichier qui servait à la fois de serveur de fichiers et de serveur Socket.IO pour un jeu HTML5 multijoueur. Je souhaite idéalement séparer le serveur de fichiers, la logique socket.IO (lire les informations du réseau et les écrire dans un tampon avec un horodatage, puis les émettre à tous les autres joueurs), et la logique du jeu.

En utilisant le premier exemple de socket.io pour illustrer mon problème, il y a normalement deux fichiers. app.js Est le serveur et index.html Est envoyé au client.

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>

Pour séparer la logique du serveur de fichiers et du serveur de jeu, j'aurais besoin de la fonction "gestionnaire" définie dans un fichier, j'aurais besoin que la fonction anonyme utilise un rappel pour que io.sockets.on () soit dans un autre fichier, et j'aurais encore besoin d'un troisième fichier pour inclure avec succès ces deux fichiers. Pour l'instant, j'ai essayé ce qui suit:

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;
    }
}

serveur de jeux:

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);
    }

}

Cela semble fonctionner (le contenu statique est correctement servi et la console montre clairement une prise de contact avec Socket.IO lorsque le client se connecte) bien qu'aucune donnée ne soit jamais envoyée. C'est comme si socket.emit () et socket.on () n'étaient jamais réellement appelés. J'ai même modifié handler () dans gameserver.js Pour ajouter console.log('User connected'); mais cela n'est jamais affiché.

Comment puis-je avoir Socket.IO dans un fichier, un serveur de fichiers dans un autre et m'attendre à ce que les deux fonctionnent correctement?

68
stevendesu

Dans socket.io 0.8, vous devez attacher des événements en utilisant io.sockets.on('...'), sauf si vous utilisez des espaces de noms, il semble que la partie sockets vous manque:

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

Il vaut probablement mieux éviter de le chaîner de cette façon (vous voudrez peut-être utiliser l'objet io plus tard). La façon dont je fais ça en ce moment:

// 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
}

Puis après avoir créé le serveur app:

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

je ferais quelque chose comme ça.

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);

et 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]);
                                }


                        });
                });
        }
};

je viens de copier et coller certains de mon ancien code - je ne sais pas vraiment ce qui a changé dans les dernières versions de socket.io, mais cela concerne plus la structure que le code réel.

et je n'utiliserais que 2 fichiers pour vos besoins, pas 3. quand vous pensez à le diviser davantage, peut-être un autre fichier pour différentes routes ...

j'espère que cela t'aides.

5
pkyeck

J'ai également eu une fissure à ce sujet et je suis assez satisfait du résultat. Consultez https://github.com/hackify/hackify-server pour le code source.

1
Michael Dausmann