Keeping Web Socket Server Alive - javascript

Zup coders. I've implemented a simple website that uses Web Sockets PHP (Consik Yii2 solution: https://github.com/consik/yii2-websocket) vs JS (Html5).
Everything is working fine, I only have one issue with my solution, making sure the server is always alive.
I though about saving the WebSocket Instance into Cache and throw a cron that checks the state of the instance. I installed memcached and found out that i can´t save a serialized version of the WebSocket Server instance. ¿Is this a good solution? ¿Would Redis Caché fix this?
I also thought about using client side JS to react to "Error during WebSocket handshake: Unexpected response code: 200" but i can't seem to get it working. I also don't like making the URL that starts websockets public.
Ex:
connect = function(){
websocket = new WebSocket(webSocketURL);
websocket.onerror = function(){
$.get( "/startWebSocketServer",
function(data){
connect();
}
);
};
};
connect();
Thanks!

I think that as matter of fact you need a process supervisor who takes care to "supervise" your server process and do actions in response of process/system events like crash, restart etc..
There are several solutions for each case (standard OS implementations, personal preferences, fit your need), here a list http://without-systemd.org/wiki/index.php/Init , Service managers section could best fit your needs.
Supervisord is easy to setup and configure, it could be a good start thanks to a good bunch of examples around the net.
Solution 1: using a cache could not be the most orthodox way to implement a custom-made supervisor.
Solution 2: is legit as long as it informs user about a problem, the call to an exposed endpoint to start a service IMHO could be a security flaw.

Related

Websockets not connected behind proxy

This is quite common problem, but I cannot find a solution to my specific case. I'm using Glassfish 4.1.1 and my application implements Websockets.
On a client side I'm connecting to WS-server simply by:
var serviceLocation = "ws://" + window.location.host + window.location.pathname + "dialog/";
var wsocket = new WebSocket(serviceLocation + token_var);
On a server side websockets are implemented via #ServerEndpoint functionality and looks very common:
#ServerEndpoint(value = "/dialog/{token}", decoders = DialogMessageDecoder.class)
public class DialogWebsoketEndpoint {
#OnOpen
public void open(final Session session, #PathParam("token") final String token) { ... }
etc.
}
Everything works fine up to the moment when customer tries to connect behind proxy.
Using this test: http://websocketstest.com/ I've found that computer of the customer works behind http-proxy 1.1.
He cannot connect to websockets, onopen simply do not fire at all. wsoscket.readyState never become 1.
How can I tune my ServerEndpoint to make this code work even when customer is connecting behind proxy?
Thank you in advance!
UPDATE: I would provide a screenshot with websocketstest at that computer:
On my computer it seems similarly except one thing:
HTTP Proxy: NO.
Much as the comments to the questions state, it seems the Proxy doesn't support Websockets properly.
This is a common issue (some cell-phone companies have proxies that disrupt websocket connections) and the solution is to use TLS/SSL connections.
The issue comes up mainly because some proxies "correct" (read: corrupt) the Websocket request headers.
However, when using TLS/SSL, the proxies can't read the header data (which is encrypted), causing data "pass-through" on most proxies.
This means the headers will arrive safely at the other end and the proxy will (mostly) ignore the connection... this might still cause an issue where connection timeouts are concerned, but it usually resolves the issue.
EDIT
Notice that the browsers will protect the client from mixing non-encrypted content with encrypted content. Make sure the script initiates the ws connections using the wss variant when TLS/SSL connections are used.

Node JS live text update with CloudMQTT

I have a node server which is connecting to CloudMQTT and receiving messages in app.js. I have my client web app running on the same node server and want to display my messages received in app.js elsewhere in a .ejs file, I'm struggling as to how best to do this.
app.js
// Create a MQTT Client
var mqtt = require('mqtt');
// Create a client connection to CloudMQTT for live data
var client = mqtt.connect('xxxxxxxxxxx', {
username: 'xxxxx',
password: 'xxxxxxx'
});
client.on('connect', function() { // When connected
console.log("Connected to CloudMQTT");
// Subscribe to the temperature
client.subscribe('Motion', function() {
// When a message arrives, do something with it
client.on('message', function(topic, message, packet) {
// ** Need to pass message out **
});
});
});
Basically you need a way for the client (browser code with EJS - HTML, CSS and JS) to receive live updates. There are basically two ways to do this from the client to the node service:
A websocket session instantiated by the client.
A polling approach.
What's the difference?
Under the hood, a websocket is full-duplex communication mechanism. That means that you can open a socket from the client (browser) to the node server and they can talk to each other both ways over a long-lived session. The pro is that updates are often times instantaneous without having to incur the cost of making another HTTP request as in the polling case. The con is that it uses a socket connection that may be long-lived, and there is typically a socket pool on any server that has limited ability to deal with many sockets. There are ways to scale around this issue, but if it's a big concern for you, you may want to go with polling.
Polling is where you set up an endpoint on your server that the client JS code hits every now and then. That endpoint will return you the updated information. The con is that you are now making a new request in order to get updates, which may not be desirable if a lot of updates are expected to come through and the app is expected to be updated in the timeliest manner possible (most of the time polling is sufficient though). The pro is that you do not have a live connection open on the server indefinitely.
Again, there are many more pros and cons, these are just the obvious ones. You decide how to implement it. When the client receives the data from either of these mechanisms, you may update the UI in any suitable manner.
From the server end, you will need a way to persist the information coming from CloudMQTT. There are multiple ways to do this. If you do not care about memory consumption and are ok with potentially throwing away old data if a client does not ask for it for a while, then it may be ok to just store this in memory in a regular javascript object {}. If you do care about persisting the data between server restarts/crashes (probably best), then you can persist to something like Redis, Mongo, any of the SQL stores if your data is relational in nature, or even a regular JSON file on disk (see fs.writeFile).
Hope this helped give you a step in the right direction!

How keep a Websocket connection persistent, even after page refresh?

I have a web application where a persistent connection from the server to it's clients (browser) is needed in order push news / updates to the clients in (near) real-time. This would not be so tricky if the navigation through some elements of the website would not cause complete page refreshs.
Polling (standard way or long polling) the server for news is not an option, since it results in often unnecessary request calls (because no news are available). Moreover news can rise up randomly. Therefore with the polling strategy the server would go down...
For the websocket (bidirectional communication channel) the client and server have to accept the upgrade to websocket.
A similar problem was discussed here, but no satisfying solution was found.
Data can survive a full page refresh by storing it in cookies or other ways:
cookies
window.name (www.thomasfrank.se/sessionvars.html)
localstorage: stores the data with no expiration date. The data will not be deleted
when the browser is closed. Example: Perseverance (github.com/viseztrance/perseverance)
PersistJS: Cross Browser Client-Side Persistent Storage without cookies Storing the
Javascript object is done, by serialize / deserialize the object.
Is there something that works similar for „running“ objects like websockets?
Some possibilities I thought of, are:
An old style „solution“ would be to put the whole web application in an iFrame and add the connection to the outermost window (of the frame). This is not an option since it causes a lot of different other problems.
Since HTML5 Share Web Workers exits, but because of the limited browser support this can also not be used.
So my question is: Is there a possibility / hack how I can keep my websocket connection open also if the page is refreshed? So that I don't have to reinitialize the connection to the server?
Simple answer - best solution is to change your server part, so it can handle connection lost and recovery (And use cookies to keep "session id" or something else).
As I cannot see any requirement to achive this literally. And even more - you can loose connection not because of referesh but because of connection problems (But you can figure out which of them happened)
I found an intereseting solution on https://crossbario.com/blog/Websocket-Persistent-Connections/. It can be achieved via SharedWorker. In your page you start it via:
var worker = new SharedWorker("worker.js");
worker.port.addEventListener("message", function(e) {
// process messages
}, false);
worker.port.start();
worker.port.postMessage("myMessageContent");
and your worker.js part looks like this:
self.addEventListener("connect", function (e) {
var port = e.ports[0];
port.start();
port.addEventListener("message", function (e) {
port.postMessage("response");
}, false);
}, false);
The full solution can be found on https://github.com/goeddea/scratchbox/tree/master/test_cases/shared_webworkers
Unfortunately according to https://caniuse.com/sharedworkers - SharedWorker works only in desktop versions of Chrome, Edge, Firefox and Opera.

PHP minimal working example of Web Sockets

I'm trying to determine how to setup a web socket for the first time ever so a working minimal example with static variables (IP address for example instead of getservbyname) will help me understand what is flowing where.
I want to do this the right way so no frameworks or addons for both the client and the server. I want to use PHP's native web sockets as described here though without over-complicating things with in-depth classes...
http://www.php.net/manual/en/intro.sockets.php
I've already put together some basic JavaScript...
window.onload = function(e)
{
if ('WebSocket' in window)
{
var socket = new WebSocket('ws://'+path.split('http://')[1]+'mail/');
socket.onopen = function () {alert('Web Socket: connected.');}
socket.onmessage = function (event) {alert('Web Socket: '+event.data);}
}
}
It's the PHP part that I'm not really sure about. Presuming we have a blank PHP file...
If necessary how do I determine if my server's PHP install has this socket functionality already available?
Is the request essentially handled as a GET or POST request in
example?
Do I need to worry about the port numbers? e.g. if
($_SERVER['SERVER_PORT']=='8080')
How do I return a basic message on the initial connection?
How do I return a basic message say, five seconds later?
It's not that simple to create a simple example, I'm afraid.
First of all you need to check in php configuration if the server is configured for sockets with the setting enable-sockets
Then you need to implement (or find) a websocket server that at least follows the Hybi10 specification (https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-10) of websockets. If you find the "magic number" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 in the code for the header, you can be sure it does follow at least Hybi06 ...
Finally, you need to have access to an admin console on the server in order to execute the PHP websocket server using php -q server.php
EDIT: This is the one I've been using a year ago ... it might still work as expected with current browsers supporting Websockets: http://code.google.com/p/phpwebsocket/source/browse/trunk/+phpwebsocket/?r=5

How to call particular node.js method from client side javascript

In my application i have created many methods in node.js file.How can i call the particular method from client side javascript.
Below is my node.js file
exports.method1=function(){
}
exports.method2=function(){
}
exports.method3=function(){
}
Your client should send a message, for example:
socket.emit("callMethod", {"methodName":"method3"});
And in your server:
socket.on("callMethod", function(data) {
if(data["methodName"] == "method3") {
exports.method3();
}
});
You don't call methods directly, you send events/messages.
I would avoid using sockets unless you really need to, from my experience they can be expensive. Sockets are great for intensive applications where a user stays engaged for awhile, otherwise I would suggest using a RESTful setup with javascript and node.js, for example:
http://blog.modulus.io/nodejs-and-express-create-rest-api
this way the socket doesn't always have to be open which causes more overhead anyway. REST will use http requests whereas sockets you will have direct connection via TCP. REST is better if your app won't be constantly engaging a user, but rather have updates here and there.

Categories