A sample chat application using Node.js and Socket.io

This entry is an attempt to demonstrate the use of Node.js and Socket.io in a sample web application. As we proceed with this, we will be developing a sample chat application.

Traditional approach


At the outset, web applications running inside a web browser are designed in such a way that the client (browser) initiates communication with the server. For instance, the browser:

  1. indicates to the server that it is interested in accessing certain service (say, get stock quotes)
  2. further tells the server what stock symbols it is interested in (say, IBM, MSFT etc)
  3. receives the stock details from the server (such as price, percent change etc.)
  4. recursively polls the server for the updated prices etc

So, there is a piece of code (such as Javascript) running in the browser constantly polling for further data from the server. Several improvements were made to streamline this approach with the introduction of AJAX, GWT etc. But, under the hood, the basic idea is still the same – client making requests to which the server responds.

Now


A different approach to addressing such requirements is to let the server push any data to the client(s) rather than having the clients “pulling” it. A few frameworks emerged lately to support this approach, one of which is WebSockets. In this write-up, I intend to walk through a simple chat application that uses this approach using node.js, socket.io and jQuery. Let’s start.

The requirement


We will be developing a chat application with the following abilities:

  1. Users pick a name before they start chatting
  2. A user can send a message to the whole room or a specific user

Installation/Setup


We need the following. Installing node.js should install “npm” as well by default. So, you can use “npm” to install the rest (express, socket.io and jade). For now, install only the node.js from the list below and proceed further.

All we need is a command line interface and a text editor (I am using vi) to work through this tutorial.

Create a folder named “sample1″ somewhere on your machine.

mkdir sample1
cd sample1

Install the require node.js modules beginning with “express”:

npm install express

This should have created a folder called “node_modules” in the current folder. Verify the installation of “express” with this command (it should print the version number of the express installed):

./node_modules/express/bin/express -V

Next, install “jade”:

npm install jade

And, verify using this:

./node_modules/jade/bin/jade -V

Next up install socket.io

npm install socket.io

Boilerplate code


Express has the ability to create most of the boilerplate code for us. Just fire it up with the current folder as the target like below (make sure your ‘pwd’ is ‘sample1′):

$ ./node_modules/express/bin/express .
destination is not empty, continue? y
create : .
create : ./package.json
create : ./app.js
create : ./public
create : ./public/javascripts
create : ./public/images
create : ./public/stylesheets
create : ./public/stylesheets/style.css
create : ./routes
create : ./routes/index.js
create : ./routes/user.js
create : ./views
create : ./views/layout.jade
create : ./views/index.jade

Install dependencies:

$ cd . && npm install

run the app:

$ node app

What this did for us is created (among other files) the helpful package.json (which contains all the details of our application including any dependent modules). Now, do as it suggests (npm install). This gets and installs any dependent modules defined in package.json (which was generated by ‘express’).

$ npm install

And, fire up the server using this:

$ node app.js
Express server listening on port 3000

Looks good. Open a browser and point it to http://localhost:3000 and feel welcomed by Express which says:

Express

Welcome to Express

You can stop the server by hitting Ctrl-C in the command window.

What is going on under-the-hood?


How did we get that welcome page? Let’s try and understand that first. This will give us an idea of how jade and express organizes the folders, control flow etc. Open up app.js file. It should be under “sample1″ folder.

The content in there should something like the following:

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path');

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

Lines 5 through 9 indicate to node.js the different modules that will be used within this file. Essentially, the functions exposed by each of those modules are available via the variable used in these lines. For example, the variable “express” can be used to access any function(s) exposed (exported) by the “express” module mentioned as argument to the require() call.

Line 11 is where use one such variable “express”. To add to your understanding, if you were to rename the variable in line 5 from var express = ... to var superExpress = ..., then line 11 should look like var app = new superExpress().

Next few lines 13 – 27 configure the “app”.

Line 29 is what I am after. It specifies that when a client (browser) requests for the root (“/”), serve it “routes.index”. But, what is routes.index? To understand that, first see line 6. See that variable “routes”? That is pointing to the module “./routes”. In simple terms, this is nothing but a folder named “routes” in the current folder (which is “sample1″). Browse to that folder and open up index.js. In there, you will find this:

/*
 * GET home page.
 */

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

See the line 5 with “exports.index”? The “.index” makes it expose (or export) a certain function as a name “index”. So, whoever uses this module will be able to call this exposed function using the name “index”.

So, when routes.index() is called at line 29 in app.js, this is the function that gets called. What is this function doing? Well, it is calling res.render() and passing it ‘index’. In other words it is rendering a page represented by “index”. By default, it uses jade and the jade files are under “sample1/views” folder. You should find a file named “index.jade” which corresponds to the first argument “index” passed to res.render(). Let’s open up index.jade and see what is in there. You will find “Welcome to #{title}” in there. And, the “title” is passed to it when we called “res.render()” above. That covers the end-to-end call of the page is rendered.

We can take it even further for a better understanding. Edit sample1/routes/index.js and change the contents to the following:

/*
 * GET home page.
 */
 exports.index = function(req, res){
  res.render('index', { title: 'Super Express' });
};

And, edit sample1/views/index.jade and change the content to the following:


extends layout
block content
  h1= title
  p Hello there, welcome back to #{title}

Now, start the server back up using “node app.js” and visit localhost:3000. Do you see your changes?

Let’s get to the real coding


Now, that we have the required modules installed, let’s begin the fun part. We are going to a develop a simple chat application that let’s users logon and send messages across to the connected clients. Here is a simple depiction of that:

Basic UI


Let’s have the basic UI in place. Before we get started on that, you will need the jQuery library. Get the “jquery-1.7.2.min.js” from this link and save a copy under “sample1/public/javascripts/jquery” folder (Create the “jquery” folder under “javascripts” folder if needed). Now, move on to edit “sample1/views/layout.jade” and change the contents to the following:


doctype 5
html
  block head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

Then, create a file “sample1/views/chat.jade” with the following content:

extends layout

block append head
  link(rel='stylesheet', href='/stylesheets/chat.css')

  script(src="/socket.io/socket.io.js")
  script(src="/javascripts/jquery/jquery-1.7.2.min.js")
  script(src="/javascripts/chat.js")

block content
  h1 Chat

  label(for="userName") User name: (Hit Enter) 
  input#userName(type="text", size="30")
  span#feedback

  p
  div#msgWindow.shadow

  p
  div
    br
    table
      tr
        td
          select#users(style="width: 100px")
        td
          input#msg(type="text", style="width: 600px", disabled="true")

Further, create a file “sample1/public/stylesheets/chat.css” with the following content:


#msgWindow {
  white-space: pre;
  overflow-y: auto;
  overflow-x: none;
  width: 700px;
  height: 550px;
}

.shadow {
  box-shadow: 2px 2px 4px 1px #000000;
  padding-top: 10px;
  padding-right: 1px;
  padding-bottom: 10px;
  padding-left: 15px;
}

With that we have the chat page outline and styling in place. We need to hook this up with express routing setup so that we can hit this page from the client. Let’s go.

Create a file “sample1/routes/chat.js” with this:


exports.main = function(req, res){
  res.render('chat', { "title" : "Chat Sample" });
};

Let’s go and use this in our app.js. Edit “sample1/app.js” and a require() for chat. Also, add require() for socket.io. We will be needing it shortly. So, the top section will have something like this:


...
  , user = require('./routes/user')
  , chat = require('./routes/chat')
  , socketio = require('socket.io')
  , http = require('http')
...

And then, add an app.get() for chat near the existing get() calls. So, it will look like this:


...
app.get('/', routes.index);
app.get('/chat', chat.main);
app.get('/users', user.list);
...

That’s it. Start (or, restart) the app. And, visit http://localhost:3000/chat. You should see something like this:

The Basic UI of the chat app

Websocket support


Now, let’s add the websockets support in our server. Edit app.js and change this line:


http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

to this:


var server = app.listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});
var io = socketio.listen(server);

Now, we need to listen to events (such as “upon client connection” or “upon a message from client” or “upon client disconnect” etc.) on this “io” instance.

Also, along the way, we will be keeping track of the connected clients with their respective user names in a local data structure (map).

Edit “sample1/app.js” and add the following towards the end of the file:


var io = socketio.listen(server);
var clients = {};

var socketsOfClients = {};
io.sockets.on('connection', function(socket) {
  socket.on('set username', function(userName) {
    // Is this an existing user name?
    if (clients[userName] === undefined) {
      // Does not exist ... so, proceed
      clients[userName] = socket.id;
      socketsOfClients[socket.id] = userName;
      userNameAvailable(socket.id, userName);
      userJoined(userName);
    } else
    if (clients[userName] === socket.id) {
      // Ignore for now
    } else {
      userNameAlreadyInUse(socket.id, userName);
    }
  });
  socket.on('message', function(msg) {
    var srcUser;
    if (msg.inferSrcUser) {
      // Infer user name based on the socket id
      srcUser = socketsOfClients[socket.id];
    } else {
      srcUser = msg.source;
    }

    if (msg.target == "All") {
      // broadcast
      io.sockets.emit('message',
          {"source": srcUser,
           "message": msg.message,
           "target": msg.target});
    } else {
      // Look up the socket id
      io.sockets.sockets[clients[msg.target]].emit('message',
          {"source": srcUser,
           "message": msg.message,
           "target": msg.target});
    }
  })
  socket.on('disconnect', function() {
    var uName = socketsOfClients[socket.id];
    delete socketsOfClients[socket.id];
    delete clients[uName];

    // relay this message to all the clients

    userLeft(uName);
  })
})

function userJoined(uName) {
    Object.keys(socketsOfClients).forEach(function(sId) {
      io.sockets.sockets[sId].emit('userJoined', { "userName": uName });
    })
}

function userLeft(uName) {
    io.sockets.emit('userLeft', { "userName": uName });
}

function userNameAvailable(sId, uName) {
  setTimeout(function() {

    console.log('Sending welcome msg to ' + uName + ' at ' + sId);
    io.sockets.sockets[sId].emit('welcome', { "userName" : uName, "currentUsers": JSON.stringify(Object.keys(clients)) });

  }, 500);
}

function userNameAlreadyInUse(sId, uName) {
  setTimeout(function() {
    io.sockets.sockets[sId].emit('error', { "userNameInUse" : true });
  }, 500);
}

Add these to your stylesheet (“sample1/public/stylesheets/chat.css”):


.allMsg {
}

.privMsg {
  font-style:italic;
}

.adminMsg {
  font-face: "verdana, helvetica";
  font-size: 8;
}

Now, on the client side, we need the code listening to the events coming from the server such as “userJoined”, “userLeft”, “welcome” and “error”. Above, we have seen that chat.jade has a reference to “/javascripts/chat.js”. The client side code goes into this script. Create or edit this file (“sample1/public/javascripts/chat.js”) with the following content:


var socket;
var myUserName;

function enableMsgInput(enable) {
  $('input#msg').prop('disabled', !enable);
}

function enableUsernameField(enable) {
  $('input#userName').prop('disabled', !enable);
}

function appendNewMessage(msg) {
  var html;
  if (msg.target == "All") {
    html = "<span class='allMsg'>" + msg.source + " : " + msg.message + "</span><br/>"
  } else {
    // It is a private message to me
    html = "<span class='privMsg'>" + msg.source + " (P) : " + msg.message + "</span><br/>"
  }
  $('#msgWindow').append(html);
}

function appendNewUser(uName, notify) {
  $('select#users').append($('<option></option>').val(uName).html(uName));
  if (notify && (myUserName !== uName) && (myUserName !== 'All'))
    $('span#msgWindow').append("<span class='adminMsg'>==>" + uName + " just joined <==<br/>")
}

function handleUserLeft(msg) {
	$("select#users option[value='" + msg.userName + "']").remove();
}

socket = io.connect("http://localhost:3000");

function setFeedback(fb) {
  $('span#feedback').html(fb);
}

function setUsername() {
	myUserName = $('input#userName').val();
    socket.emit('set username', $('input#userName').val(), function(data) { console.log('emit set username', data); });
    console.log('Set user name as ' + $('input#userName').val());
}

function sendMessage() {
    var trgtUser = $('select#users').val();
    socket.emit('message', 
                {
                  "inferSrcUser": true,
                  "source": "",
                  "message": $('input#msg').val(),
                  "target": trgtUser
                });
	$('input#msg').val("");
}

function setCurrentUsers(usersStr) {
	$('select#users >option').remove()
	appendNewUser('All', false)
	JSON.parse(usersStr).forEach(function(name) {
		appendNewUser(name, false);
	});
	$('select#users').val('All').attr('selected', true);
}

$(function() {
  enableMsgInput(false);

  socket.on('userJoined', function(msg) {
    appendNewUser(msg.userName, true);
  });
  
  socket.on('userLeft', function(msg) {
    handleUserLeft(msg);
  });

  socket.on('message', function(msg) {
    appendNewMessage(msg);
  });

  socket.on('welcome', function(msg) {
	setFeedback("<span style='color: green'> Username available. You can begin chatting.</span>");
	setCurrentUsers(msg.currentUsers)
    enableMsgInput(true);
	enableUsernameField(false);
  });

  socket.on('error', function(msg) {
	  if (msg.userNameInUse) {
		  setFeedback("<span style='color: red'> Username already in use. Try another name.</span>");
	  }
  });
  
  $('input#userName').change(setUsername);
  $('input#userName').keypress(function(e) {
	  if (e.keyCode == 13) {
		  setUsername();
		  e.stopPropagation();
		  e.stopped = true;
		  e.preventDefault();
	  }
  });
  
  $('input#msg').keypress(function(e) {
	  if (e.keyCode == 13) {
		  sendMessage();
		  e.stopPropagation();
		  e.stopped = true;
		  e.preventDefault();
	  }
  });
});

Save all and start/restart the server. Browse to http://localhost:3000/chat. Start with entering a user name. Open multiple browser windows/tabs each with a different user name and chat away and see how the messages get relayed.

The source code for what we covered so far can be found here: Source code on github

Possible improvements


Some improvements that you can work beyond what is in here:

  1. What happens when a user picks a name “All”?
  2. Provide the ability for the users to pick their text color etc. as a preference
  3. Ability to create rooms

38 Responses to A sample chat application using Node.js and Socket.io

  1. Encik Wady says:

    It’s not working. in console window, it looks like the app is requesting from localhost
    http://localhost:3000/socket.io/1/?t=1351106826018
    in public/javascripts/chat.js,
    i’m trying to change socket = io.connect(“http://localhost:3000″); to my public ip but not working too. Am i missing something? anyway good tutorial.

    • vijayannadi says:

      Thanks for the comment.

      Where is this app deployed/hosted? To have your client point to socket.io on your host, you could change this line
      socket = io.connect(“http://localhost:3000″);
      to
      var socket = io.connect(document.location);

      I have a different sample hosted here, for example: http://aqueous-beyond-8981.herokuapp.com/

  2. Alina says:

    Getting error Error: Can’t set headers after they are sent.

    • vijayannadi says:

      When is this coming? During server startup?

      • after user open the webpage

      • Same here, just downloaded the source code from git hub and started the application. As soon as i access the localhost:3000/chat url i get this error
        PS C:\…\sample1> node .\app.js
        info – socket.io started
        Express server listening on port 3000
        GET /chat 200 36ms – 686

        http.js:707
        throw new Error(‘Can\’t set headers after they are sent.’);
        ^
        Error: Can’t set headers after they are sent.
        at ServerResponse.OutgoingMessage.setHeader (http.js:707:11)
        at ServerResponse.res.setHeader (C:\…\sample1\node_modules\express\node_modules\co
        nnect\lib\patch.js:59:22)
        at next (C:\…\sample1\node_modules\express\node_modules\connect\lib\proto.js:153:1
        3)
        at Function.app.handle (C:\…\sample1\node_modules\express\node_modules\connect\lib
        \proto.js:198:3)
        at Server.app (C:\…\sample1\node_modules\express\node_modules\connect\lib\connect.
        js:66:31)
        at Manager.handleRequest (C:\…\sample1\node_modules\socket.io\lib\manager.js:564:2
        8)
        at Server. (C:\…\sample1\node_modules\socket.io\lib\manager.js:118:10)
        at Server.EventEmitter.emit (events.js:117:20)
        at HTTPParser.parser.onIncoming (http.js:2056:12)
        at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:120:23)
        PS C:\…\sample1>

    • I got the same error, what should we do?

  3. I am getting the following error
    d:\tools\sample1\routes\chat.js:35
    socket = io.connect(document.location);
    ^
    ReferenceError: io is not defined
    at Object. (d:\tools\sample1\routes\chat.
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Object. (d:\tools\sample1\app.js:12:12
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)

    • Ebuzz says:

      Looks like you mixed up the two chat.js files in the example. That one is supposed to be client-side, in /public/javascripts/, not /routes/

  4. Sunny says:

    Newbie: I wanted to know about the missing package.json i am not using Vi editor, but just a notepad for text. What should i write in package.json to install the npms thanks you!

    • vijayannadi says:

      package.json should have been created for you. In any case, it contains something like this:


      {
      "name": "application-name",
      "version": "0.0.1",
      "private": true,
      "scripts": {
      "start": "node app"
      },
      "dependencies": {
      "express": "3.0.0rc4",
      "jade": "*"
      }
      }

  5. Nice Demo, Its really useful.

    Thanks Vijay

  6. Ryan says:

    Great example!

    Why do you use a timeout of 500 on the server side before sending a response? It seems to work just as well with a value of 10, or even without using a timeout at all. I think I understand the reasoning behind using a timeout for asynchronous flow, but is there really a need for such a long delay?

    • Ryan says:

      Nevermind, I see why now. Without the timeout, the new username ends up getting added twice in the list of users. Though another fix for that is to swap the order of:

      userNameAvailable(socket.id, userName);
      userJoined(userName);

      …instead calling userJoined first.

  7. quiero informar que para estudiar existen muchas alternativas hoy en dia los frameworks escritos en javascript cada vez son mas existen una variedad muy amplia la cuestion es saber utilizar y aprovecharlos al maximo para sus beneficios economicos y capaz que sociales,tengo muuuuchooo sueñoooooo!!!!!:………..

  8. Brian says:

    Hi,
    Great post. One question, how can I keep the socket logic separate from app.js. Just can’t figure out how to keep my main app.js clean.

  9. Shariq says:

    Hi,

    Great example. It helps..
    how can we implement the same picking the usernames from the database?

    Thanks
    Shariq

  10. Vrushali says:

    Hi Vijay,

    I am not able to install express, jade and socket.io due to proxy at our end. How to configure npm for proxy settings?

    • vijayannadi says:

      Try this:
      npm config set proxy http://“user:password”@:
      npm config set https-proxy http://“user:password”@:

      • Vrushali says:

        Hi Vijay,

        Tried that but no luck :(

        Even tried directly providing the proxy settings while executing install command as follows:
        npm –https-proxy=http://user:password@proxy.persistent.co.in:8080 -g install express

        But this is also not working :( Am I missing something?

      • Vrushali says:

        Hi Vijay,

        Thanks for this wonderful example.

        I have resolved proxy problem and now I am able to join the chat. I am getting the message “Username available. You can begin chatting.” but after that, nothing is editable. And on command prompt following messages are shown:

        debug – emitting heartbeat for client hEwWiWY9aEFVLpM_ysmh
        debug – websocket writing 2::
        debug – set heartbeat timeout for client hEwWiWY9aEFVLpM_ysmh
        debug – got heartbeat packet
        debug – cleared heartbeat timeout for client hEwWiWY9aEFVLpM_ysmh
        debug – set heartbeat interval for client hEwWiWY9aEFVLpM_ysmh
        debug – emitting heartbeat for client hEwWiWY9aEFVLpM_ysmh
        debug – websocket writing 2::
        ….
        ….

        Am I missing something?

  11. Paula says:

    Hi, thanks a lot for this tutorial, I’ve beeen reading some tutorials and this one is the best!

    I have a doubt about node: I don’t understand where it has to be installed, and if once installed in one folder do I need to install it in every folder app?
    What happen if I want to start another app? Do I need to create another folder and install express, jade,.. again or is there a way to install all globally?

    Thanks a lot and excuse my poor english :-/

  12. dileephell says:

    C:\Users\mark\Downloads\chat-master>nodemon app.js
    7 Jan 15:45:55 – [nodemon] v1.0.5
    7 Jan 15:45:55 – [nodemon] to restart at any time, enter `rs`
    7 Jan 15:45:55 – [nodemon] watching: *.*
    7 Jan 15:45:55 – [nodemon] starting `node app.js`
    info – socket.io started
    Express server listening on port 3000
    GET / 200 88ms – 180

    http.js:691
    throw new Error(‘Can\’t set headers after they are sent.’);
    ^
    Error: Can’t set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
    at ServerResponse.res.setHeader (C:\Users\mark\Downloads\chat-master\node_modules\express\node_modules\connect\lib\patch.js:59:22)
    at next (C:\Users\mark\Downloads\chat-master\node_modules\express\node_modules\connect\lib\proto.js:153:13)
    at Function.app.handle (C:\Users\mark\Downloads\chat-master\node_modules\express\node_modules\connect\lib\proto.js:198:3)
    at Server.app (C:\Users\mark\Downloads\chat-master\node_modules\express\node_modules\connect\lib\connect.js:66:31)
    at Manager.handleRequest (C:\Users\mark\Downloads\chat-master\node_modules\socket.io\lib\manager.js:564:28)
    at Server. (C:\Users\mark\Downloads\chat-master\node_modules\socket.io\lib\manager.js:118:10)
    at Server.EventEmitter.emit (events.js:117:20)
    at HTTPParser.parser.onIncoming (http.js:2108:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
    7 Jan 15:46:03 – [nodemon] app crashed – waiting for file changes before starting…

  13. benarjee says:

    Express
    500 Error: /home/prathap/sample1/views/layout.jade:1 > 1| doctype 5 2| html 3| block head 4| title= title`doctype 5` is deprecated, you must now use `doctype html`

    at Object.Lexer.doctype (/home/prathap/sample1/node_modules/jade/lib/lexer.js:252:13)
    at Object.Lexer.next (/home/prathap/sample1/node_modules/jade/lib/lexer.js:833:15)
    at Object.Lexer.lookahead (/home/prathap/sample1/node_modules/jade/lib/lexer.js:113:46)
    at Parser.lookahead (/home/prathap/sample1/node_modules/jade/lib/parser.js:111:23)
    at Parser.peek (/home/prathap/sample1/node_modules/jade/lib/parser.js:88:17)
    at Parser.parse (/home/prathap/sample1/node_modules/jade/lib/parser.js:126:26)
    at Parser.parse (/home/prathap/sample1/node_modules/jade/lib/parser.js:140:24)
    at parse (/home/prathap/sample1/node_modules/jade/lib/jade.js:95:62)
    at Object.exports.compile (/home/prathap/sample1/node_modules/jade/lib/jade.js:152:9)
    at Object.exports.render (/home/prathap/sample1/node_modules/jade/lib/jade.js:256:15)

    i got this error.how to fix it???

  14. benarjee says:

    i dnt get any action press enter…

  15. zain says:

    I am getting error of “can not call method connect of undefined in chat.js file what should i do now

  16. micheal says:

    john@ubuntu:~/All_nodejs/chat_server_from_web/real/chat-master$ node-dev app.js info – socket.io started
    Express server listening on port 3000
    GET /chat 200 140ms – 686
    Error: Can’t set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
    at ServerResponse.res.setHeader (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/express/node_modules/connect/lib/patch.js:59:22)
    at next (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/express/node_modules/connect/lib/proto.js:153:13)
    at Function.app.handle (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/express/node_modules/connect/lib/proto.js:198:3)
    at Server.app (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/express/node_modules/connect/lib/connect.js:66:31)
    at Manager.handleRequest (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/socket.io/lib/manager.js:564:28)
    at Server. (/home/john/All_nodejs/chat_server_from_web/real/chat-master/node_modules/socket.io/lib/manager.js:118:10)
    at Server.EventEmitter.emit (events.js:117:20)
    at HTTPParser.parser.onIncoming (http.js:2108:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
    [ERROR] 07:28:48 Error

  17. Pratik Kumar says:

    thanks for the code. I tried to implement it. it is not showing any error but the dropdown and the other features are not functioning, nothing happens after enter the username and hit ENTER

  18. TTirimo says:

    Great post and easy to follow.I have the chat up and running but I notice that once I post a chat it does not appear in the chat message board.How can I enable to view my chat messages.
    Secondly how can I integrate a notification script.

  19. John Sextro says:

    Vijay,

    Thanks for the walk through. It was extraordinarily beneficial for me. You are clearly an expert with node and socket.io.

  20. ankitraturi says:

    Nice demo its working fine
    But when I run this demo on LAN. this doesn’t work
    can you solve it

  21. Imran Bughio says:

    throw new Error(‘Can\’t set headers after they are sent.’);

  22. Ajit says:

    Hi Vijay, its working well, great stuff!!!

  23. Can you please explain these lines

    var server = app.listen(app.get(‘port’), function(){
    console.log(“Express server listening on port ” + app.get(‘port’));
    });

    var io = socketio.listen(server);

  24. aviseksingh says:

    Hi Vijay thanks working like a charm great. One thing i want to ask can we integrate html files rather then jade for view if possible can you give an example. Thanks

  25. Pingback: 10 Node.Js Example App + Tutorial for 2014 - Fresh Web Dev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: