0

I found a tutorial that helped me set up a basic real-time collaborative drawing page. It works perfectly on localhost:8080, but I wanted to start it on my server, and I ran into some problems.

app.js

    // Including libraries

    var app = require('http').createServer(handler),
    io = require('socket.io').listen(app),
    static = require('node-static'); // for serving files

    // This will make all the files in the current folder
    // accessible from the web
    var fileServer = new static.Server('./');

    // This is the port for our web server.
    // you will need to go to http://localhost:8080 to see it
    app.listen(8080);

    // If the URL of the socket server is opened in a browser
    function handler (request, response) {

      request.addListener('end', function () {
        fileServer.serve(request, response); // this will return the correct file
      });
    }

    // Delete this row if you want to see debug messages
    io.set('log level', 1);

    // Listen for incoming connections from clients
    io.sockets.on('connection', function (socket) {

      // Start listening for mouse move events
      socket.on('mousemove', function (data) {

        // This line sends the event (broadcasts it)
        // to everyone except the originating client.
        socket.broadcast.emit('moving', data);
      });
    });

script.js

$(function() {

  // This demo depends on the canvas element
  if(!('getContext' in document.createElement('canvas'))){
    alert('Sorry, it looks like your browser does not support canvas!');
    return false;
  }

  // The URL of your web server (the port is set in app.js)
  var url = 'http://localhost:8080';

  var doc = $(document),
  win = $(window),
  canvas = $('#paper'),
  ctx = canvas[0].getContext('2d'),
  instructions = $('#instructions');

  // Generate an unique ID
  var id = Math.round($.now()*Math.random());

  // A flag for drawing activity
  var drawing = false;

  var clients = {};
  var cursors = {};

  var socket = io.connect(url);

  socket.on('moving', function (data) {

    if(! (data.id in clients)){
      // a new user has come online. create a cursor for them
      cursors[data.id] = $('<div class="cursor">').appendTo('#cursors');
    }

    // Move the mouse pointer
    cursors[data.id].css({
      'left' : data.x,
      'top' : data.y
    });

    // Is the user drawing?
    if(data.drawing && clients[data.id]){

      // Draw a line on the canvas. clients[data.id] holds
      // the previous position of this user's mouse pointer

      drawLine(clients[data.id].x, clients[data.id].y, data.x, data.y);
    }

    // Saving the current client state
    clients[data.id] = data;
    clients[data.id].updated = $.now();
  });

  var prev = {};

  canvas.on('mousedown',function(e){
    e.preventDefault();
    drawing = true;
    prev.x = e.pageX;
    prev.y = e.pageY;

    // Hide the instructions
    instructions.fadeOut();
  });

  doc.bind('mouseup mouseleave',function(){
    drawing = false;
  });

  var lastEmit = $.now();

  doc.on('mousemove',function(e){
    if($.now() - lastEmit > 30){
      socket.emit('mousemove',{
        'x': e.pageX,
        'y': e.pageY,
        'drawing': drawing,
        'id': id
      });
      lastEmit = $.now();
    }

    // Draw a line for the current user's movement, as it is
    // not received in the socket.on('moving') event above

    if(drawing){

      drawLine(prev.x, prev.y, e.pageX, e.pageY);

      prev.x = e.pageX;
      prev.y = e.pageY;
    }
  });

  // Remove inactive clients after 10 seconds of inactivity
  setInterval(function(){

    for(ident in clients){
      if($.now() - clients[ident].updated > 10000){

        // Last update was more than 10 seconds ago.
        // This user has probably closed the page

        cursors[ident].remove();
        delete clients[ident];
        delete cursors[ident];
      }
    }

  },10000);

  function drawLine(fromx, fromy, tox, toy){
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();
  }

});

When I put that on my server, it only works if I have two pages open on the same browser, but not with friends on other computers. I think it's because of the calls I'm making to localhost on the code. However, I have no idea of what to replace them with.

I have all the node packages installed on my server and I'm starting it the same way I started it on localhost:

node assets/js/app.js

The output I get is:

node assets/js/app.js 
   info  - socket.io started
   warn  - error raised: Error: listen EADDRINUSE

That warning, I don't get it on the local machine.

Charles
  • 50,943
  • 13
  • 104
  • 142
David Gomes
  • 5,644
  • 16
  • 60
  • 103

2 Answers2

1

Use server ip address instead of localhost.

In app.js app.listen(port, ip)

In script.js var url = 'http://<ip>:8080';

vinayr
  • 11,026
  • 3
  • 46
  • 42
  • Is there a way I can pass the URL instead of the IP? – David Gomes Sep 29 '12 at 10:47
  • 1
    sure...just replace ip with url – vinayr Sep 29 '12 at 10:47
  • Ok, so I tried that, and it still doesn't work. I also changed the port to 83 instead of 8080. I'm getting a new warn `warn - error raised: Error: getaddrinfo ENOENT`. I have `app.listen(83, "http://57o9.org")` and `var url = "http://57o9.org:83"` – David Gomes Sep 29 '12 at 10:53
  • 2
    listen doesn't necessarly take the url as argument, remove it. Just app.listen(83) (for testing I would listen on higher port to avoid conflict with system). – AsTeR Sep 29 '12 at 11:36
1

I'm not a node guy. I suggest you to watch : Node / Express: EADDRINUSE, Address already in use - Kill server

EADDRINUSE might mean that something is already running on the same port / same interface on the computer. Look at the answer, they suggest you to look for old node instance, if that doesn't work. Just try to bind another port than 8080.

And yes, as said @vinayr don't bind on localhost, your client would only try to connect on local connections.

Community
  • 1
  • 1
AsTeR
  • 7,247
  • 14
  • 60
  • 99