Websockets on nodejs - Managing ws instances

259 views
Skip to first unread message

Ray Jender

unread,
Feb 20, 2016, 9:26:54 PM2/20/16
to nodejs

Please bear with me as I am new to websockets.

So, my problem is keeping track of websocket instances.
I am trying to modify some existing open source javascript code.

I have server.js, index.js and index.html files. As with any website,
it could have many users browsing the page. There is only a single
webpage.

The basic operation is: index.html --> index.js --> server.js --> index.js

What I am having a hard time wrapping my head around is associating the
websocket with the browser.   What I want to do  is be able to update
each webpage with the number of users.  I have googled tons of sites but
I am still very confused on how this should work.

I've seen a thing like ws.broadcast, but  I am having a hard time trying to
implement that.  It seems that the way the opensource code I am using initializes
websockets way different than the examples I am seeing.

I am using node v0.10.42, npm 1.4.29, express 4.12.4, minimist 1.1.1, ws 0.7.2, bower 1.4.1

I need a tutor to help me through this!  Care to volunteer?   I would be so appreciative!!!

Thanks,

Ray


Christopher Mina

unread,
Feb 20, 2016, 11:48:55 PM2/20/16
to nodejs
Hi Ray, 

Whenever I use a websocket, I track the origin of the socket.  In my case, I add a query param with some identifying information such as an authkey which was dynamically generated on page load and inserted into the client via javascript.  When I make the request to open the socket server, using socket.io, it looks something like this:

socket = io(connectUrl + "?authkey=" + connectKey, {forceNew: true});

:and on the server side, there is something that looks like this

oServer = new IOServer(server);
ioServer.origins(appConfig.origins);
ioServer.use(verifyConnection);
ioServer.on('connection', onConnect);

Notice the verifyConnection middleware being used, that looks like this, removing the unimportant bits...

var verifyConnection = function(socket, next) {
var authkey = socket.request._query.authkey;
 

};


Christopher Mina

unread,
Feb 20, 2016, 11:48:55 PM2/20/16
to nodejs
Sorry about that half finished post, my last post was sent prematurely...

What I was getting at is that I now have access to the authkey during the setup phase.  I can use this auth key to query the database for information about that user and store it.  Now I have a way to directly associated the incoming websocket with a specific user.  

I'll now store the actual websocket instances in one or more hash maps, and when I need to, for instance, send a single user some information, i can query that websocket via the socketUserId hash map.  Or if I want to send everyone a message, I'll loop through a list where I keep a reference to all sockets, and send each one the message individually.   This is just one way of doing it.  There are other more appropriate pub/sub mechanisms as well you could investigate. 

Hopefully that helps a little bit. 
-Chris


On Saturday, February 20, 2016 at 7:26:54 PM UTC-7, Ray Jender wrote:

Ray Jender

unread,
Feb 21, 2016, 9:24:51 AM2/21/16
to nodejs
Thanks for the reply Chris.

One of the confusions I am having is trying to impliment something written for socket.io  to use in ws.

But that said, I do have code to get the authkey, but I am confused how the authkey can be used to access the webpage?

So for code, I have:

function nextUniqueId() {
        idCounter++;
        return idCounter.toString();
}

wss.on('connection', function(ws) {

        var sessionId = nextUniqueId();
        console.log('Connection received with sessionId ' + sessionId);

        var id = ws.upgradeReq.headers['sec-websocket-key'];
        console.log('New Connection id : : ', id);

So sessionid just counts the number of users, which is what I want to display on all user pages.

Right now, each user webpage is only showing what the total user count is when the user created the ws.
(1,2,3,4, etc).  So the first user is showing 1, the second user is showing 2, and so on,

So I am confused on how the var id above can be used to send data to a particular webpage (websocket)?


Thanks,

Ray

Christopher Mina

unread,
Feb 21, 2016, 9:56:05 PM2/21/16
to nod...@googlegroups.com
Hi Ray. 

You'll want to keep a reference to each web socket created (in an array or object hash) and a property on your server or in a database to track the number of active sessions. When a new connection is made (or closed), you will increment / decrement the count and then send a message event through each socket to the client. The client will be listening for that event (eg "count_changed") and when the event comes through, it will read the new count off the data payload of the event and render it to the screen. 

I'm not sure if I'm answering your question or not. Maybe you are asking specifically about the particular library you're using? It seems to me, the confusion may just be in how you maintain a reference to each open web socket. 

For instance :

var sockets = [];
wss.on('connection', function(ws) {
    sockets.push(ws);
}

You can now reference any socket created via this array. You'll want to ensure you are removing disconnected sockets as well, by listening for a disconnect event. 

Hopefully this helps. 
Chris 


--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to a topic in the Google Groups "nodejs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nodejs/DVNUsoEhoRM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/0b7f961d-35a9-48e4-9dff-d79c9322f9bd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Christopher Mina

Live Healthy. Work Hard. Be Kind. Gain Success.

Ray Jender

unread,
Feb 22, 2016, 12:01:13 PM2/22/16
to nodejs
I am definitely using a particular library, ws.
Is the sockets.push(ws) a valid command for that?  I could not find it anywhere?

Thanks,

Ray
To unsubscribe from this group and all its topics, send an email to nodejs+unsubscribe@googlegroups.com.

To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/0b7f961d-35a9-48e4-9dff-d79c9322f9bd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sávio Lucena

unread,
Feb 22, 2016, 6:22:52 PM2/22/16
to nod...@googlegroups.com
Hey Ray,

I haven’t been following this thread but from what I can infer of Chris’s answer ’sockets’ is a javascript Array to store and keep reference of each ws instance created, ‘push’ is just adding an instance to it :).


You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.

To post to this group, send email to nod...@googlegroups.com.

Christopher Mina

unread,
Feb 22, 2016, 6:34:14 PM2/22/16
to nodejs
That's correct, just a normal array.  

I was just showing an example of how to use the array to store a reference to all open web sockets.  Then when you need to increment, you'd just iterate over the array.  

e.g. 

var myCount = 10;
sockets.forEach(function(ws) {
    ws.emit("countupdated", myCount);
});

And your client side code would listen for the "countupdated" event, something like:

clientSocket.on("countupdated", function(data) {
    console.log("The new count is " + data);
});


I'm still not sure if any of this is answering your question, though...
-Chris
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.

To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/0b7f961d-35a9-48e4-9dff-d79c9322f9bd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


-- 
Christopher Mina

Live Healthy. Work Hard. Be Kind. Gain Success.

Ray Jender

unread,
Feb 22, 2016, 6:58:14 PM2/22/16
to nodejs
Ok I think I am now saving endpoint ID's as such:

On the server side:

var idCounter = 0;

function nextUniqueId() {
        idCounter++;
        return idCounter.toString();
}

var TotalViewers = 0;
var viewersID = [ ];

wss.on('connection', function(ws) {

 var sessionId = nextUniqueId(); /* sessionId is a simple counter for # of viewers */

        console.log('Connection received with sessionId ' + sessionId);
        TotalViewers = TotalViewers + sessionId; /* Keep a running total of viewers and new viewers (sessionId's) */

 var ids = ws.upgradeReq.headers['sec-websocket-key']; /* ids is the unique endpoint identifier? */
        viewersID[sessionId] = ids;
        console.log('New Connection viewerid : : ', viewersID[sessionId]);

Now, how do I update each webpage (ids) with the value of TotalViewers?  I'm pretty sure I understand looping through for (x = 1 x<=sessionId, sessionId--)  viewersID[sessionId]=TotalViewers;
but I can't wrap my head around how this actually gets to the webpage? I think my code above is correct but maybe not.

I appreciate comments...

Ray

Ray Jender

unread,
Feb 22, 2016, 7:12:01 PM2/22/16
to nodejs
Getting close.  Please see my previous post.

Ray

Ray Jender

unread,
Feb 22, 2016, 7:31:36 PM2/22/16
to nodejs
On the client side, I am expecting json?  And I do not have a clientSocket.on?
What I have is:

ws.onmessage = function(message) {
        var parsedMessage = JSON.parse(message.data);
        console.info('Received message: ' + message.data);

        switch (parsedMessage.id) {

There a few different "case" situations like  'Stop', 'Default', etc.

Ray

Christopher Mina

unread,
Feb 22, 2016, 7:51:23 PM2/22/16
to nodejs
Ok, I finally actually checked out your library to help you a litle bit more.  

It looks like your ws library on the server actually maintains a list of open / connected clients, so this is actually pretty trivial.  

You'll be able to do something like this:

wss.on('connection', function(ws) {
    numConnections
++;
   
var message = JSON.stringify({
        numConnections
: numConnections,
       
event: "numConnectionsChanged"
   
});

    wss
.clients.forEach(function(client) {
        client.send(message);
   
});
 
})

Now in your client side, you would do something like this:

ws = new WebSocket(...);
ws
.onmessage =function(event) {
   
var data = JSON.parse(event.data);
   
if (data.event == "numConnectionsChanged") {
        var numberOfConnections = data.numConnections;
        document
.getElementById("my-counter").innerHTML = numberOfConnections;
   
}
}


In this solution, you don't really care about the sessions or anything else.  You just care about the total number of connected clients, and you just want to inform them. 

Remember, you'll want to handle the disconnect in a similar way. 

-Chris

Ray Jender

unread,
Feb 23, 2016, 9:30:27 PM2/23/16
to nodejs
Well, with your help, I now have it half working!  It is updating each webpage for new connections.  Now I have to figure out how to decrement when a user leaves.
I will work on that and let you know.

I really appreciate your help with this.  You helped a blind man see!

Ray

Christopher Mina

unread,
Feb 23, 2016, 11:01:23 PM2/23/16
to nodejs
You're welcome.  

As a hint, you can look at this for managing the disconnects:

ws.on('close', function close() {
  numConnections--;
  ... alert all remaining sockets ...
});

Best of luck.
Chris

Ray Jender

unread,
Feb 24, 2016, 6:18:46 PM2/24/16
to nodejs
Got it.  Now for some testing!

Thanks again.

Ray
Reply all
Reply to author
Forward
0 new messages