Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Separating file server and socket.io logic in node.js

Separating file server and socket.io logic in node.js

Problem

I'm fairly new to node.js and I've found its quite complicated separating a project into multiple files as the project grows in size. I had one large file before which served as both a file server and a Socket.IO server for a multiplayer HTML5 game. I ideally want to separate the file server, socket.IO logic (reading information from the network and writing it to a buffer with a timestamp, then emitting it to all other players), and game logic.

Using the first example from socket.io to demonstrate my problem, there are two files normally. app.js is the server and index.html is sent to the 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:

To separate file server and game server logic I would need the Function "handler" defined in one file, I would need the anonymous function used a callback for io.sockets.on() to be in another file, and I would need yet a third file to successfully include both of these files. For now I have tried the following:

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

gameserver:

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

}

This seems to work (the static content is properly served and the console clearly shows a handshake with Socket.IO when the client connects) although no data is ever sent. It's as though socket.emit() and socket.on() are never actually called. I even modified handler() in gameserver.js to add console.log('User connected'); however this is never displayed.

How can I have Socket.IO in one file, a file server in another, and still expect both to operate correctly?

Problem courtesy of: stevendesu

Solution

In socket.io 0.8, you should attach events using io.sockets.on('...'), unless you're using namespaces, you seem to be missing the sockets part:

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

It's probably better to avoid chaining it that way (you might want to use the io object later). The way I'm doing this right now:

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

Then after creating the server app:

// main.js
var io = require('./lib/sockets').listen(app)
Solution courtesy of: Ricardo Tomasi

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Separating file server and socket.io logic in node.js

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×