nicktendo
nicktendo

Reputation: 607

Socket IO: RangeError: Maximum call stack size exceeded

Every time a client connects to my nodejs server, my server crashes with the error 'RangeError: Maximum call stack size exceeded'. I believe I must have a recursive issue somewhere, but it is eluding me.

My server:

require('monitor').start();
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

var allClients = [];

io.on('connection', function(socket){
  console.log('user joined: ' + socket.request.connection.remoteAddress + ':' + socket.request.connection.remotePort);
  socket.address = socket.request.connection.remoteAddress;
  socket.port = socket.request.connection.remotePort;
  socket.name = '';
  socket.xPos = 0;
  socket.yPos = 0;
  //io.emit('new user', socket.address + '_' + socket.port);

  // Send current client list to new connection
  socket.emit('client list', allClients);

  // Only send 'new user' event to previously connected clients, not the new client.
  var i = 0;
  for(i=0;i<allClients.length;i++){
    allClients[i].emit('new user', socket.address + '_' + socket.port);
  }

  // Push new socket into the client array after the array has been sent to all other users
  allClients.push(socket);

  socket.on('chat message', function(msg){
    io.emit('chat message', socket.address + ':' + socket.port + ": " + socket.name + ' says: ' + msg);
    console.log(socket.address + ":" + socket.port + ": " + socket.name + ' says: ' + msg);
  });

    socket.on('set_name', function(msg){
    //io.emit('chat message', socket.address + ':' + socket.port + ': ' + msg);
    socket.name = msg;
    console.log(socket.address + ":" + socket.port + ' set name to: ' + msg);
  });

  socket.on('xPosUpdate', function(msg){
    //io.emit('chat message', socket.address + ':' + socket.port + ': ' + msg);
    console.log(socket.address + ":" + socket.port + ' set xPos to: ' + msg);
  });

  socket.on('yPosUpdate', function(msg){
    //io.emit('chat message', socket.address + ':' + socket.port + ': ' + msg);
    console.log(socket.address + ":" + socket.port + ' set yPos to: ' + msg);
  });

  socket.on('disconnect', function() {
    io.emit('user disconnect', socket.address + '_' + socket.port);
    io.emit('chat message', socket.address + ':' + socket.port + ": " + socket.name + ' disconnected.');
      console.log('Got disconnect!');
    socket = null;
      var i = allClients.indexOf(socket);
      allClients.splice(i, 1);
   });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

And then handling the socket on the client side:

var users = [];
      $('#chatInput').submit(function(){
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
      });
        $('#nameInput').submit(function(){
        socket.emit('set_name', $('#n').val());
        $('#n').val('');
        return false;
      });
            socket.on('client list', function(msg){
        $('#messages').append($('<li>').text('Processing client list...'));
                var i = 0;
              for(i=0;i<msg.length;i++){
                $('#messages').append($('<li>').text('Client ' + i + ': ' + msg[i].address + ':' + msg[i].port + ', Name: ' + msg[i].name));
              }
      });
      socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
      });
            socket.on('user disconnect', function(msg){
        users[msg].unset();
      });
            socket.on('new user', function(msg){
                users[msg] = [];
                users[msg].xPos = 0;
                users[msg].yPos = 0;
        $('#messages').append($('<li>').text(msg));
      });

Upvotes: 2

Views: 3655

Answers (3)

nicktendo
nicktendo

Reputation: 607

Thank you for the responses.

After a bit of experimentation I realized the overflow error was triggering due to the volume of data I was attempting to emit in the following line on the server:

socket.emit('client list', allClients);

When a new user connects I am pushing the entire connection object into the "allClients" array. The amount of data contained in a connection object is too large to be sent via socket.emit and caused the RangeError.

I will have to simplify the client list data being emitted to each new client to avoid this..."stack overflow".. :)

Upvotes: 4

Steeve Pitis
Steeve Pitis

Reputation: 4453

Instead of your loop you may use this (this will be the same result) :

socket.broadcast.emit('new user', socket.address + '_' + socket.port);

then you can remove this part:

socket = null;
var i = allClients.indexOf(socket);
allClients.splice(i, 1);

But I'm not sure it is the problem. I'm guessing about your socket.name = msg;. I'm not really sure you are able to update this object. It's better to remove this.

Upvotes: 0

Simpson Kamonere
Simpson Kamonere

Reputation: 85

// Only send 'new user' event to previously connected clients, not the new client.
  var i = 0;
  for(i=0;i<allClients.length;i++){
    allClients[i].emit('new user', socket.address + '_' + socket.port);
  }

The above code sample looks a bit suspicious to me. Did you check the value of allClients.length? As a sidenote why initialise the value of i twice?variable

Upvotes: -1

Related Questions