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

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:

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

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?

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)

Separating file server and socket.io logic in node.js, IO server for a multiplayer HTML5 game. I ideally want to separate the file server, socket.IO logic (reading information from the network and  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.

i would do something like this.

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

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


                        });
                });
        }
};

i just copy&pasted some of my old code - don't really know what changed in the last versions of socket.io, but this is more about the structure than the actual code.

and i would only use 2 files for your purposes, not 3. when you think about splitting it up further, maybe one other file for different routes ...

hope this helps.

Express Server and WebSocket Servers in different files? : node, But like I said, the reason that I am separating the servers into different files is server and the logic for my WebSocket server into different files (basically into server to express immediately. var io = require("socket.io")(); io.attach(server,  Stackoverflow - Separating file server and socket.io logic in node.js Stackoverflow - Loading socket.io as a module in KrakenJS/Express Kraken issue - Socket.IO example

I have had a crack at this as well and I am fairly happy with the result. Check out https://github.com/hackify/hackify-server for source code.

Node.js Websocket Examples with Socket.io, Of the many different websocket libraries for Node.js available to us, I chose to Server(app); var io = require('socket.io')(server); app.get('/', function(req, res) { res​. Or maybe you want need strict separation of logic between different parts of  Stack Overflow Public questions and answers; Node.js client for a socket.io server. 59. Separating file server and socket.io logic in node.js. 0.

I've another solution. You can use require.js creating a module and pass "app" as an argument. Within the module you can start socket.io and organize your sockets.

app.js:

  var requirejs = require('requirejs');

  requirejs.config({
      baseUrl: './',
      nodeRequire: require
  });

  requirejs(['sockets'], function(sockets) {

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

      // do something
      // add more sockets here using "io" resource

  });

In your socket.js module you can do something like this:

  define(['socket.io'], function(socket){
    return function(app){
      var server = app.listen(3000) 
        , io     = socket.listen(server);

      io.sockets.on('connection', function (socket) {
        console.log('connected to socket');

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

        // more more more

      });

      return io;
    }
  });

I hope help you with my contribution.

Socket.IO, It consists of: a Node.js server: Source | API a Javasc. IO allows you to create several Namespaces, which will act as separate communication channels but  I have socket.io sending a basic object from server to client. This bit works fine. Now want to send a stream from server to client, using event-stream (specifically the results of a block-chain q

Separating socket.io event logic into module - node.js - html, I would like to keep my server.js file "clean" and have all the socket related events in a separate file. I also want to be able to fire an event from within my route  I'm trying to use Socket.io with Node.js and emit to a socket within the logic of a route. I have a fairly standard Express 3 setup with a server.js file that sits in the route, and then I have an index.js which sits in a routes folders that exports all the pages/publically accessible functions of the site.

Smashing Node.js: JavaScript Everywhere, keep the chat logic separate from the markup, into its own file called chat.js. One of the handy aspects of Socket.IO is that when it appends itselfto http.Server​  I want to upload a file to server by socket.io. because my socket.io client is under apache. and socket.io server is in Node.js. I want to code uploading of file in Node.js. But how I can send the file data to the node.js listening to socket. I have tried the upload of a file using Node.js server. This link is here but the this code does not

Node.js v14.2.0 Documentation, Example: sending a server object; Example: sending a socket object --trace-​events-enabled; --trace-exit; --trace-sigint; --trace-sync-io; --trace-tls addon_node.c is a separate file that contains the Node.js specific entry point to the function which will be called when the asynchronous logic is completed or is cancelled. socket.io express example (2) The amount of bandwidth will depend heavily on the amount of data you're going to send from the server, and how much data the client will send. The bandwidth usage will also depend on which Socket.IO transport you're using, and the heartbeat interval of your application.

Comments
  • do you know the express js framework? expressjs.com it's great and really helps you structure your application. there are a ton of examples on github (github.com/visionmedia/express/tree/master/examples) maybe there's something that can help you with your problem...
  • @pkyeck: I'm reading up on expressjs now to try and figure out how it can benefit me, but so far it seems more complicated than what I need. All I really want is to separate my logic for the game server and the file server into two separate files then have a third file which properly starts both servers.
  • did you have the time to check out my "new" answer?
  • @pkyeck I've looked at it, although it seems like it's only masking the problem and not solving it. Not sockets.js is the ONE MASSIVE FILE instead of app.js. I'd like to have no single massive files but instead separate files for every function. More and more node.js seems like more of a hassle than a blessing.
  • Great answer, trying to port this to krakenJS but the socket.io module never starts :/
  • We arent using 'return io' right? it's just for the var io.
  • If I want to trigger an emit request ? for ex., app.get('/some/url',function(req,res){ // I want to emit here })
  • Right now it's just a file server and a socket.io server, however eventually I will also have game logic to determine player positions given movement updates and I will need to have lag minimization logic which looks at the ping of each client and estimates which game state they are currently in judging from the existing data. Having some logic to fast-forward time, some logic to rewind time, some logic to move players, some logic to handle network data, and some logic to handle files meant I wanted to separate EVERYTHING into different files, ideally. Not just the socket.io stuff.
  • it's just the beginning - with the files you posted. you can do more than one var xxx = require('./xxx'); and split your app into multiple files. i was at the mongodb conf yesterday and someone from 10gen showed a game based on node/mongo/websockets (github.com/christkv/mongoman) he's sending BSON data over the socket and decodes the data on the client - makes for a faster communication between client/server ... maybe it's interesting for you!?
  • In case anyone reading this is wondering, no, there is no reason at all to use AMD within node.
  • It's just an alternative, isn't the only way to do