Thursday, August 30, 2012
Wednesday, August 22, 2012
Basic Extendable Node.js Push Service
Assuming that you have already installed Node.js and NPM manager, in this article i'll show you basic implementation on the push service based on web sockets. First you should install great web socket library.
https://github.com/Worlize/WebSocket-Node/
npm install websocket
There is also httpclient lib in the package that should be in the same lib folder as userservice.js, messageservice.js and wsmanager.js. This client is used for easy communication with RESTful web services. You can download from the official git repo.
https://github.com/billywhizz/node-httpclient
In the following sources you can see how is easy to implement extendable service on top on Node with using web sockets.
This basic implementation can be used for various realtime services, realtime push notifications, chat and im, multiplayer game servers and so on. In the next post i'll show basic implementation on IM client and server side based on web sockets, implemented with using this concept.
Sources are free for every purpose.
Enjoy.
wsserver.js
wsmanager.js
messageservice.js
userservice.js
https://github.com/Worlize/WebSocket-Node/
npm install websocket
There is also httpclient lib in the package that should be in the same lib folder as userservice.js, messageservice.js and wsmanager.js. This client is used for easy communication with RESTful web services. You can download from the official git repo.
https://github.com/billywhizz/node-httpclient
In the following sources you can see how is easy to implement extendable service on top on Node with using web sockets.
This basic implementation can be used for various realtime services, realtime push notifications, chat and im, multiplayer game servers and so on. In the next post i'll show basic implementation on IM client and server side based on web sockets, implemented with using this concept.
Sources are free for every purpose.
Enjoy.
wsserver.js
var WebSocketServer =
require('websocket').server;
var http = require('http');
var sys = require("sys");
var wsManagerLib =
require("./lib/wsmanager");
var wsManager = new
wsManagerLib.WSManager();
var server =
http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
});
wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request',
function(request) {
if (!originIsAllowed(request.origin)) {
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin
+ ' rejected.');
return;
}
var connection = request.accept('', request.origin);
connection.on('message', function(message) {
if (message.type === 'utf8') {
//console.log('Received
Message ' + message);
wsManager.protocolValidator(message.utf8Data, connection, request);
} else if (message.type === 'binary') {
console.log('Received Binary
Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log('closing connection. Reason: '+description);
});
});
|
wsmanager.js
var userService =
require("./userservice");
var userServiceManager = new
userService.UserService();
//userServiceManager.setModel();
var messageService =
require("./messagesservice");
var messageServiceManager = new
messageService.MessagesService();
function WSManager() {
/**
* Protocol validator, validate JSON
instructions and takes appropriate
* actions
*
* @param protocolMessage
* @param connection
* @param req
* @returns {Number}
*/
this.protocolValidator
= function(protocolMessage, connection, req) {
try
{
var
protocolObj = JSON.parse(protocolMessage);
}
catch (e) {
return
0;
}
if(!protocolObj.data
|| !protocolObj.data.params)
{
return
0;
}
var
protocolObjectData = protocolObj.data;
var
protocolObjectDataParams = protocolObjectData.params;
if
(protocolObj.caller !== "user" && protocolObj.caller !==
"system" && protocolObjectData.userHash !== false) {
req.reject();
return
0;
}
console.log("DEBUG:"+protocolObjectData.method);
switch(protocolObj.caller)
{
case
'system' :
break;
case
'user' :
switch(protocolObjectData.method)
{
case
'login' :
userServiceManager.createNewConnectionDataObjectIfNOTExist(1,
protocolObjectData, connection, req);
break;
case
'testhi' :
messageServiceManager.anonymousHi(connection);
break;
default:
break;
}
break;
default:
break;
}
};
}
exports.WSManager = WSManager;
|
messageservice.js
function MessagesService() {
this.messagesData
= {
systemMessage
: {
caller
: "system",
data
: {
method
: "",
params
: {}
}
},
};
this.systemMsg
= {
caller
: "system",
data
: {
method
: "",
params
: {}
}
};
this.pushMessage
= function(userObject, messageType) {
userObject.connection.sendUTF(JSON.stringify(messageType));
};
/**
* Push message notification to client
*
* @param connection
*/
this.pushMessageNotif
= function(connection, count) {
count
= typeof count !== 'undefined' ? count : 1 ;
this.systemMsg.data.method
= 'pushmessage';
this.systemMsg.data.params
= { messageIterator : count };
//
console.log(JSON.stringify(this.systemMsg));
connection.sendUTF(JSON.stringify(this.systemMsg));
};
/**
* Push number of all active users
*
* @param connection
* @param numberOfActiveUsers
*/
this.pushUsersNumberToClient
= function(connection, numberOfActiveUsers) {
this.systemMsg.data.method
= 'pushnumusers';
this.systemMsg.data.params
= { numUsersIterator : numberOfActiveUsers };
//
console.log(JSON.stringify(this.systemMsg));
connection.sendUTF(JSON.stringify(this.systemMsg));
};
/**
* Push the number of active users to all
active users
*
*/
this.pushNumberOfUsersToAllActiveUsers
= function(globalBase) {
//
var numberOfActiveUsers = this.countAllActiveUsers();
for
(key in globalBase) {
var
userObj = globalBase[key];
if
(userObj !== undefined && userObj !== null && userObj.active
=== true) {
this.pushUsersNumberToClient(userObj.connection,
this.numberOfActiveLoggedUsers);
}
}
};
this.sayHi
= function(userObject) {
this.systemMsg.data.method
= 'systemmsg';
this.systemMsg.data.params
= { msg : "Hi from NodeJS "+userObject.userName };
//console.log(JSON.stringify(this.systemMsg));
userObject.connection.sendUTF(JSON.stringify(this.systemMsg));
};
this.anonymousHi
= function(connection) {
this.systemMsg.data.method
= 'systemmsg';
this.systemMsg.data.params
= { msg : "Hi from NodeJS "};
connection.sendUTF(JSON.stringify(this.systemMsg));
};
}
exports.MessagesService =
MessagesService;
|
userservice.js
var httpcli =
require("./httpclient");
var messageService =
require("./messagesservice");
var messageServiceManager = new
messageService.MessagesService();
function UserService() {
this.globalUsersBase
= {};
this.numberOfActiveLoggedUsers
= 0;
/**
* Test valid user on REST web service
*
* @param userHash
* @returns
*/
this.testValidUserByHASH
= function(userHash) {
var
url =
"http://localhost/phd/index.php/usermanager/checkexistinguser?h="+userHash;
var
client = new httpcli.httpclient();
var
getResult;
client.perform(url,
"GET", function(result) {
getResult
= result;
});
return
getResult;
};
/**
* Create new user connection object into the
global users objects store
*
* @param callerType
* @param protocolObjectData
* @param connection
* @returns { }
*/
this.createNewConnectionDataObjectIfNOTExist
= function(callerType, protocolObjectData, connection, request) {
var
dataObj = this.globalUsersBase[protocolObjectData.userHash];
connection.userHash
= protocolObjectData.userHash;
if
(!dataObj) {
dataObj
= {
connectionType
: callerType,
userHash
: protocolObjectData.userHash,
userName
: protocolObjectData.userName,
fullName
: protocolObjectData.fullName,
userType
: protocolObjectData.params.userType,
ip
: connection.remoteAddress,
connection
: connection,
userHirearchy
: protocolObjectData.params.userHirearchy,
activeFriends
: [],
messages
: [],
emails
: [],
unSeenMessages
: {
messagesFromFriends
: [],
otherMessages
: []
},
active
: true
};
this.globalUsersBase[protocolObjectData.userHash]
= dataObj;
this.numberOfActiveLoggedUsers
+= 1;
}
else {
if
(dataObj.userHash == connection.userHash && dataObj.active === true)
{
dataObj.connection
= null;
dataObj.connection
= connection;
}
}
if
(dataObj.active === false) {
dataObj.active
= true;
this.numberOfActiveLoggedUsers
+= 1;
}
messageServiceManager.pushNumberOfUsersToAllActiveUsers(this.globalUsersBase);
if
(!dataObj.connection || dataObj.connection.state === "closed") {
dataObj.connection
= null;
dataObj.connection
= connection;
}
messageServiceManager.sayHi(dataObj);
return
dataObj;
};
/**
* Set live user object as disconnected
*
*/
this.setActiveUserASDisconnected
= function(connection) {
userHash
= connection.userHash;
if
(!this.globalUsersBase[userHash] ||
(this.globalUsersBase[userHash].connection && connection !==
this.globalUsersBase[userHash].connection) ) {
return
0;
}
if
(this.globalUsersBase[userHash].active === true) {
this.globalUsersBase[userHash].active
= false;
this.numberOfActiveLoggedUsers
-= 1;
messageServiceManager.pushNumberOfUsersToAllActiveUsers();
}
};
/**
* Check if element exist in the array
*
* @param arrayList
* @param obj
* @returns
*/
this.containObj
= function(arrayList, obj) {
elementExist
= false;
for
(var element in arrayList) {
if
(arrayList[element] === obj) {
elementExist
= true;
break;
}
}
return
elementExist;
};
/**
* Remove single element from the array
*
*/
this.removeByIndex
= function(arrayName,arrayIndex){
arrayName.splice(arrayIndex,1);
};
/**
* Counts and return number of active users
in global users object
*
*/
this.countAllActiveUsers
= function() {
var
localCounter = 0;
for
(key in this.globalUsersBase) {
var
userObj = this.globalUsersBase[key];
if
(userObj !== undefined || userObj !== null) {
localCounter++;
}
}
return
localCounter;
};
/**
* Index of value in array
*
* @param arrayForSearch
* @param valueInArray
* @returns
*/
this.indexOf
= function(arrayForSearch, valueInArray) {
indexCounter
= -1;
for
(var i in arrayForSearch) {
if
(arrayForSearch[i] === valueInArray) {
indexCounter
= i;
break;
}
}
return
indexCounter;
};
/**
* Return the size of global users list
*
*/
this.sizeOfGlobalUsersObject
= function() {
return
Object.keys(this.globalUsersBase).length;
};
}
exports.UserService = UserService;
|
Subscribe to:
Posts (Atom)