Integrate socket.io into angularjs project

I am trying to add socket.io to my angularjs project. My reference is http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/?redirect_from_locale=zh#disqus_thread. I am trying to modify it as below:

About the socket.io server: app.js:

var express = require('express');
var app = module.exports = express();

var server = require('http').createServer(app);

// Hook Socket.io into Express
var io = require('socket.io').listen(server);

// Socket.io Communication

var socket = require('./scripts/socket.js');
io.sockets.on('connection', socket);

// Start server at http://127.0.0.1:3000

server.listen(3000, function() {
console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});

scripts/socket.js:

// Keep track of which names are used so that there are no duplicates
var userNames = (function () {
  var names = {};

  var claim = function (name) {
    if (!name || names[name]) {
      return false;
    } else {
      names[name] = true;
      return true;
    }
  };

  // find the lowest unused "guest" name and claim it
  var getGuestName = function () {
    var name,
      nextUserId = 1;

    do {
      name = 'Guest ' + nextUserId;
      nextUserId += 1;
    } while (!claim(name));

    return name;
  };

  // serialize claimed names as an array
  var get = function () {
    var res = [];
    for (user in names) {
      res.push(user);
    }

    return res;
  };

  var free = function (name) {
    if (names[name]) {
      delete names[name];
    }
  };

  return {
    claim: claim,
    free: free,
    get: get,
    getGuestName: getGuestName
  };
}());

// export function for listening to the socket
module.exports = function (socket) {
  var name = userNames.getGuestName();

  // send the new user their name and a list of users
  socket.emit('init', {
    name: name,
    users: userNames.get()
  });

  // notify other clients that a new user has joined
  socket.broadcast.emit('user:join', {
    name: name
  });

  // broadcast a user's message to other users
  socket.on('send:message', function (data) {
    socket.broadcast.emit('send:message', {
      user: name,
      text: data.message
    });
  });

  // validate a user's name change, and broadcast it on success
  socket.on('change:name', function (data, fn) {
    if (userNames.claim(data.name)) {
      var oldName = name;
      userNames.free(oldName);

      name = data.name;

      socket.broadcast.emit('change:name', {
        oldName: oldName,
        newName: name
      });

      fn(true);
    } else {
      fn(false);
    }
  });

  // clean up when a user leaves, and broadcast it to other users
  socket.on('disconnect', function () {
    socket.broadcast.emit('user:left', {
      name: name
    });
    userNames.free(name);
  });
};

These are all the files for socket.io. After node app.js, it displays "Express server listening on port 3000 in development mode"


The angular part is modified from the angular seed: https://github.com/angular/angular-seed index.html:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <meta charset="UTF-8">
  <title>Angular Socket.io IM Demo App</title>
  <link rel="stylesheet" href="css/app.css"></head>
<body>
  <h1>Angular Socket.io IM Demo App</h1>
  <div ng-controller="AppCtrl">
    <div class="col">
      <h3>Messages</h3>
      <div class="overflowable">
        <p ng-repeat="message in messages" ng-class="{alert: message.user == 'chatroom'}">: </p>
      </div>
    </div>
    <div class="col">
      <h3>Users</h3>
      <div class="overflowable">
        <p ng-repeat="user in users"></p>
      </div>
    </div>
    <div class="clr">
      <form ng-submit="sendMessage()">
        Message:
        <input size="60" ng-model="message">
        <input type="submit" value="Send"></form>
    </div>
    <div class="clr">
      <h3>Change your name</h3>
      <p>Your current user name is </p>
      <form ng-submit="changeName()">
        <input ng-model="newName">
        <input type="submit" value="Change Name"></form>
    </div>
  </div>
  <script src="lib/angular/angular.js"></script>
  <script src="/socket.io/socket.io.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
  <script src="js/filters.js"></script>
  <script src="js/directives.js"></script>
</body>
</html>

js/app.js:

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']);       

js/services.js:

angular.module('myApp.services', [])
.value('version', '0.1')
.factory('socket', function($rootScope) {
    var socket = io.connect(); 
    return {
        on: function(eventName, callback) {
            socket.on(eventName, function() {
                var args = arguments;
                $rootScope.$apply(function() {
                    callback.apply(socket, args);
                });
            });
        },
        emit: function(eventName, data, callback) {
            socket.emit(eventName, data, function() {
                var args = arguments;
                $rootScope.$apply(function() {
                    if (callback) {
                        callback.apply(socket, args);
                    }
                });
            })
        }
    };
});

js/controllers.js:

/* Controllers */

function AppCtrl($scope, socket) {

  // Socket listeners
  // ================
  socket.on('init', function (data) {
    $scope.name = data.name;
    $scope.users = data.users;
  });

  socket.on('send:message', function (message) {
    $scope.messages.push(message);
  });

  socket.on('change:name', function (data) {
    changeName(data.oldName, data.newName);
  });

  socket.on('user:join', function (data) {
    $scope.messages.push({
      user: 'chatroom',
      text: 'User ' + data.name + ' has joined.'
    });
    $scope.users.push(data.name);
  });

  // add a message to the conversation when a user disconnects or leaves the room
  socket.on('user:left', function (data) {
    $scope.messages.push({
      user: 'chatroom',
      text: 'User ' + data.name + ' has left.'
    });
    var i, user;
    for (i = 0; i < $scope.users.length; i++) {
      user = $scope.users[i];
      if (user === data.name) {
        $scope.users.splice(i, 1);
        break;
      }
    }
  });

  // Private helpers
  // ===============

  var changeName = function (oldName, newName) {
    // rename user in list of users
    var i;
    for (i = 0; i < $scope.users.length; i++) {
      if ($scope.users[i] === oldName) {
        $scope.users[i] = newName;
      }
    }

    $scope.messages.push({
      user: 'chatroom',
      text: 'User ' + oldName + ' is now known as ' + newName + '.'
    });
  }

  // Methods published to the scope
  // ==============================

  $scope.changeName = function () {
    socket.emit('change:name', {
      name: $scope.newName
    }, function (result) {
      if (!result) {
        alert('There was an error changing your name');
      } else {

        changeName($scope.name, $scope.newName);

        $scope.name = $scope.newName;
        $scope.newName = '';
      }
    });
  };

  $scope.messages = [];

  $scope.sendMessage = function () {
    socket.emit('send:message', {
      message: $scope.message
    });

    // add the message to our model locally
    $scope.messages.push({
      user: $scope.name,
      text: $scope.message
    });

    // clear message box
    $scope.message = '';
  };
}

Then I run the angularjs in localhost:8000. In the webpage it seems I can send something which caused the bower to update:

[Mon, 28 Jul 2014 20:10:13 GMT] "GET /app/lib/angular/angular.js" "Mozilla/5.0 (
Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.1
53 Safari/537.36"
[Mon, 28 Jul 2014 20:10:13 GMT] "GET /socket.io/socket.io.js" "Mozilla/5.0 (Wind
ows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 S
afari/537.36"

However the socket.io running on localhost:3000 receives nothing.

I guess I must have something wrong in the connection between angularjs and socket.io, such as the

<script src="/socket.io/socket.io.js"></script> 

in the index.html, or the

var socket = io.connect(); 

in the js/services.js.

I tried to change them to

<script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script>

or

<script src="http://localhost:3000/socket.io/socket.io.js"></script>

or

var socket = io.connect('http://127.0.0.1:3000');

or

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

or

var socket = io.connect('http://localhost');

but nothing works. Maybe I am on a completely wrong way.

So I copy paste my code here, hope someone can help me. Any help or suggestions will be grateful.

UPDATE Now it seems the client can connect to the server, but can't load the controller correctly. Not sure how to fix it.

Finally figured out what's wrong with the code above after an entire day.

1.The client should connect the socket.io server by adding explicit IP, that is:

in the services.js:

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

in the index.html:

<script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script>  

2.Notice that there are no path and file lib/angular/angular.js in the angular-seed folder. Need to manually create the folder and add the file.

3.The code in the quesion did not display the data correctly.

This is the code I fixed all the bugs and it can work smoothly. https://github.com/shaosh/angular-socketio-chatroom-example