Websockets: Detecting a disconnected client

5,486 views
Skip to first unread message

Daniel Mckenna

unread,
May 13, 2015, 4:59:14 AM5/13/15
to node...@googlegroups.com
Hi Folks,
Is it possible for node-red to detect clients disconnecting from a websocket? Or to output the number of currently connected users similar to socket.io?

For my application I would like clients to open a websocket and send a request message - the server would then continually send the client unique data (e.g. data unique to its session_id, broadcast is not an option) for as long as the websocket is opened.

Any suggestions on how to handle this? Thanks!

Nicholas O'Leary

unread,
May 13, 2015, 5:48:46 AM5/13/15
to Node-RED Mailing LIst
HI Daniel,

this topic came up recently regarding the TCP socket nodes: how should we notify when clients connect/disconnect. 

There we some thoughts raised, but we didn't come to a conclusion - we need to revive that thread as it applies just as much to the ws nodes.

My preferred approach would be to add an option to these nodes to emit connect/disconnect events, (off by default so they behaviour as they do today unless turned on). What these event messages looks like still needs to be defined - setting payload to something like 'connect' 'disconnect' would not be distinguishable from a data package with the same content. Maybe an event type property on the already-present msg._session object.

Nick

--
http://nodered.org
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniel Mckenna

unread,
May 13, 2015, 6:29:07 AM5/13/15
to node...@googlegroups.com
Thanks Nick.
Looks like this is the thread you referenced: https://groups.google.com/d/topic/node-red/7pt7bBWZKg4/discussion

I will play with some of the suggestions made there and see what makes sense.

Daniel.

Dave C-J

unread,
May 13, 2015, 8:27:36 AM5/13/15
to node...@googlegroups.com
currently my "preferred" option is that we send a msg with msg.connected set true or false and msg.payload either null or with whatever was left in the input buffer (eg in the case of the tcp node)... that way it applies across tcp, ws, mqtt (possibly serial ?) etc - and doesn't rely on a sessionid.

Dean Sellers

unread,
May 15, 2015, 10:14:14 PM5/15/15
to node...@googlegroups.com
Hi everyone,

I am still using my hacked version of the tcp node from the referenced thread. It would be great to have a released node that does the job.

Since in my use case the listening tcp node feeds into a function node it doesn't matter too much how it is implemented, I will have to change some code, but as yet I only have one site requiring this I can manage it, msg.connected === true/false works fine for me.

D'o

Dave C-J

unread,
May 16, 2015, 12:02:58 PM5/16/15
to node...@googlegroups.com
Hi Dean,

spookily Nick and i were just talking about it on Friday... getting nearer the top of the pile.
msg.connected still favourite. 

Stefano Costa

unread,
Sep 24, 2015, 8:06:39 AM9/24/15
to Node-RED
Any progress on this? ie is it now possible to detect a connect / disconnect event on a TCP listening node?

S

Nicholas O'Leary

unread,
Sep 24, 2015, 8:08:24 AM9/24/15
to Node-RED Mailing LIst
It will be in the 0.12 release.

Nick



--

Walter Kraembring

unread,
Sep 25, 2015, 12:30:57 AM9/25/15
to Node-RED
Hello,

That's one side of the thing, Node-RED detecting  that clients are disconnecting. But the clients also need to detect when they are getting disconnected (at least to somehow inform the user that the connection is broken)

I have personally spent a massive amount of time on my client code so that they automatically reconnects and gets synchronized with latest data if they would loose the connection with the server. 

Once one of my clients gets connected, 
  • it sends a status update request and receives latest data
  • starts to monitor it's connection, i.e. it is expecting websocket messages within a certain time period
After this initial step, if the connection state is changed, means no websocket messages within the time out period, 
  • the background color of the browser is changed to notify the user about the broken connection
  • the browser re-initiate the websocket connection and tries to re-connect until successful
In my case this has worked out very well, I have a number of android tablets mounted on the walls in the house and if I have to reboot Node-RED (very seldom needed) all the tablets will automatically go into normal operation once Node-RED is up again. It is so convenient, all tablets automatically reconnected & synchronized when necessary. If you have many concurrent clients that you want to have connected continuously, this is a must I think.

Kind regards, Walter

Dave C-J

unread,
Sep 25, 2015, 1:35:41 AM9/25/15
to node...@googlegroups.com

Yes, I do similar for my websocket connected web pages. Usually I have some small indicator to show that the page/data is still live. But this is just standard websocket javascript code and nothing to do with Node-RED per se.

What we are doing is making all node statuses available in the next release.

Walter Kraembring

unread,
Sep 25, 2015, 1:39:10 AM9/25/15
to Node-RED
But this is just standard websocket javascript code and nothing to do with Node-RED per se


That is understood ;)

But nevertheless, important if you wanna build a complete system that is able to recover itself from interruptions

Julian Knight

unread,
Sep 25, 2015, 3:41:14 AM9/25/15
to Node-RED
This is indeed true and there is an alternative JS library for websockets that will auto reconnect sensibly. Can;t remember the name but I use it in my pages.

Adam S

unread,
Apr 20, 2016, 8:51:52 AM4/20/16
to Node-RED
I have also created a good bit of code to deal with disconnected websockets (below), but there are 2 things that I cannot figure out.

First: if the page is just sitting there not sending data to the websocket it and gets disconnected it will never know that it is not connected any more.  I made a workaround for now that sends data every 5 seconds to the websocket, but wondering if there is a better solution? 
Second: the timeout when the disconnection happens is too long for me.  After data is sent without a reply the page will wait 30 seconds before it decides its disconnected.  I need it to wait only ~5 seconds before it gives up.

/* Runs when the page load has completed */
window
.onload = function() {
   
/* Attempt a connection */
    connect
();
}

/* Before the page closes, disconnect cleanly from the server */
window
.onbeforeunload = function() {
    disconnect
();
}

/* This function disconnects the websocket and optionally attempts to reconnect */
function disconnect(retry=false) {
   
/* If connected, disconnect */
   
if (isopen) socket.close();
   
/* if retry is specified, attempt to reconnect */
   
if (retry) reconnect();
}
/* This function handles connecting to the server */
function connect() {
   
/* if not connected... */
   
if (!isopen) {
       
var wsUri = "ws:";
       
var loc = window.location;
       
if (loc.protocol === "https:") { wsUri = "wss:"; }
        wsUri
+= "//" + loc.host + loc.pathname.replace("pagename","ws/websocketname");
        socket
= new WebSocket(wsUri);
       
//socket = new WebSocket(`ws://${location.host}/ws/updatescheduletest`, 'MyServerProtocol');

       
/* When the socket connects... */
        socket
.onopen = function() {
           
/* Display message in console if debug is enabled */
           
if (options.debug) console.log('Connected!');
            isopen
= true;
       
}

       
/* When a message from the server is received ... */
        socket
.onmessage = function(e) {
           
/* Reset wait time- make sure this matches the value set earlier */
            wait
= 5;
           
if (options.debug) console.log('Rx Successful! : ' + e.data);
           
/* Get the data from the message */
           
var payload = JSON.parse(e.data);
       
}

       
/* when sending data to the server ... */
        socket
.onsend = new function(e) {
           
if (options.debug) console.log('Tx Successful!');
       
}

       
/* When socket connection closes... */
        socket
.onclose = function(e) {
           
if (options.debug) console.log('Disconnected!');
            isopen
= false;
           
/* Clear socket */
            socket
= null;
       
}

       
/* When an error occurs- aka an unplanned disconnect... */
        socket
.onerror = function(e) {
           
if (options.debug) console.error('Socket error! ', e.message, ' Closing socket!');
           
/* Close connection and retry to connect */
            disconnect
(true);
       
}
   
}
}
/* This function attempts to reconnect without filling the network with spam */
function reconnect() {
   
/* if not connected ... */
   
if (!isopen || socket.readyState == 3) {
       
if (options.debug) console.log("Disconnected: Trying to reconnect in ", wait, " seconds.");
       
/* Attempt to reconnect in 'wait' seconds */
        setTimeout
(function() { connect(); }, wait * 1000 );
       
/* Increase wait time up to a minute between consecutive tries*/
       
if (wait <= 60) wait *= 2;
   
}
}


Julian Knight

unread,
Apr 20, 2016, 4:21:55 PM4/20/16
to Node-RED
You might find this helpful:


I use it in my debug and live update flows.

Dave C-J

unread,
Apr 20, 2016, 6:35:55 PM4/20/16
to node...@googlegroups.com

Nice spot.

Adam S

unread,
Apr 21, 2016, 12:36:22 PM4/21/16
to Node-RED
Thanks for the link Julian, unfortunately I did pretty much everything there on my own...would have been a good resource a few days ago lol.

To answer my own question, the timeout is actually set by the browser config.  After hours of testing some heartbeat code I made up, I found this gem: http://stackoverflow.com/questions/18918028/websockets-chrome-and-firefox-differences I was under the assumption the timeout was a server or client JS setting that I was unable to find.
Reply all
Reply to author
Forward
0 new messages