WebSocket client with socketio/engineio - websocket

I have a really simple nodejs app into which I've installed socket.io and engine.io (not at the same time).
I'm trying to connect from a standard WebSocket client (new WebSocket)
The first issue I had is that the client would not connect at all, I've 'fixed' that by setting 'destroy upgrade' to false on the server.
Now the socket is trying to connect (the readystate is 0) but I'm not getting a connection event on the server or an onopen event on the client, so I'm guessing it's never connecting.
Do I need to set anything else to get the connection to happen?
The server is running express and listening on port 3000 (socket.io piggybacks onto the http server created for express)
The client does a
new WebSocket("ws://localhost:3000")
I've also tried
new WebSocket("ws://localhost:3000/socket.io")
As the socket.io docs imply that that is the default endpoint but neither work

I worked this out the old fashioned way (by looking at the network traffic) when what I should have done is look at the signal.io docs, oh well. There are two parts to this, connecting and sending data.
To connect, the client has to negotiate using xhr, so:
var time = new Date().getTime();
$.get("http://localhost:3000/socket.io/1/?t=" + time, function (data) {});
This starts the negotiation that socket io requires. Socket.io returns an id, some timeouts and a list of protocols, all of which I ignore apart from the id
// in the xhr callback function
var key = data.split(":")[0];
var ws = new WebSocket('ws://localhost:3000/socket.io/1/websocket/' + key);
and that connects
To send data to a socket.io server you have to frame the data in the format it expects which is documented here https://github.com/LearnBoost/socket.io-spec
something like
ws.send('5:::{"name":"my other event","args":[{"my":"data"}]}');

Related

How to structure Socket.io Authentication

I am creating an application using Flask-SocketIO at the server side and a javascript Socket.IO client. (There will also be a Python client later). I want to ensure users are authenticated before they connect to the web socket server.
I have created a PHP login form to check the username and password. If these are valid then a unique token is returned and the token is also inserted into a table on the server. The token is passed to the client side javascript, where it is submitted with the request to create a web socket connection.
As I understand it Flask-SocketIO will simply accept the connection and I need to put my validation code under the #socketio.on('connect') decorator. (I assume a server based implementation of Socket.IO works in a similar way). Therefore my code checks the submitted token against the database table and if it is valid the web socket connection is simply allowed to happen. However if the token is not valid I issue a disconnect() command. The javascript client does not try the connection again, which is what I want in this scenario.
Here is where it gets tricky...
I would like to write a disconnect handler on the client side using socket.on('disconnect', function() { //do something }); to allow the user to reconnect when the socket is broken due to a poor mobile connection for example. How can I distinguish an accidental disconnection from an intentional one due to failed validation?
Conversely, I would like to alert the user to the fact that their validation process failed. But how to distinguish that from a scenario where the the socket is broken due to a poor mobile connection?
I would like to write a disconnect handler on the client side using socket.on('disconnect', function() { //do something }); to allow the user to reconnect when the socket is broken due to a poor mobile connection for example.
There is no need for you to worry about reconnection. The Socket.IO client protocol includes reconnection support and will always try to reconnect when the connection is lost. To verify this, start your server, connect with a client, and then kill your server. A little bit later restart the server and you will see that in a matter of seconds the connection is reestablished.

When the server opens the socket connection it is flooded with messages from the clients

I start the server and the clients.
Then I close the server, and after few minutes reopen it.
I get too many messages (from the client).
How do I reset it, to start clean.
The server code:
var io = require('socket.io').listen(3001);
var games=[];
console.log('start1 server.js');
setTimeout(clear_games,30000);
io.sockets.on('connection', function(socket)
{
When your active socket.io clients lose the connection to the server, they will constantly try to reconnect until your server comes back online and they successfully get a reconnection. This is the normal and expected behavior and is generally a very useful features since the client will then automatically restablish a connect after a temporary server restart or interrupted network connection.
If you just want to start over for testing purposes, then close all the client web pages, shut down your server, then restart your server, then open the client web pages again. Because the client web pages will not be open when you start your server, it should not immediately get a bunch of reconnects.
If you never want the client to automatically reconnect, then you can specify that in an option in the client code that connects to the server with an option of {reconnection: false}, (though that is generally a bad idea because now the client won't auto-recover if the connection is temporarily interrupted).
What I did is:
In the client, I added a monitor function that is invoked (setTimeout) every second, and checks the socket.connected.
If it is not connected, I don't send any messages to the server till I see that it is true (connected) again.
This solved the problem.

How reconnect from server to client

I'am able to detect when client disconnect from a server by this code:
self._session.socket.on("close", function() {
console.log("client disconnected");
}
But how can I try reconnect to the disconnected client?
You cannot connect from server to client as client isn't listening to the websocket, but just connecting (to the server).
However, you can put a code in your client to reconnect it at onclose (or just close) event. Generally this occurs by recreating the WebSocket object in the client with the correct parameters.
Something as:
function connect(){
var mywebsocket = new WebSocket("ws://(your url)");
// ... my callbacks and functions...
mywebsocket.onclose = connect; // or arguments.callee
}
connect();
Should work correctly. ;)
Good luck.
If the client got disconnected for some reason (internet connection disruption/server issues) it will automatically reconnect on its own. To see how many attempts have been made or the status have a look at http://docs.meteor.com/#meteor_status
Since version 0.6.3 if the internet was disconnected. As soon as the internet is back it will attempt to reconnect too.
To reconnect from your code somewhere you can run Meteor.reconnect() from the client.
Unfortunately the meteor client can't listen for connections from the server so the server can't initiate a reconnection, you need some kind of connection to a server to send a message to the client to do something such as a reconnection.

In websocket how does server identify a client's webserver

If I am not wrong, to have a push technology the client ( say browser ) also needs to run a small web server which is listening on some port ( say ijetty runs on 8080 ). Now when the actual server comes to know about any event, it sends the event to client. This way there is no PULL mechanism involved at all. Is this right ? OR there is a persistent connection involved and server sends the data on that connection whenever the event happens. My question is : in the former case ( if it is true ), how does server know about client's IP ?
WebSockets working with socket based on TCP connection, basically the client make a request for connection to the server with a challenge, websocket version, ip and more data, then the server decrypts the challenge and return his result back to the client, this process called Handshake.
If the handshake is approved, the connection is made, the socket connection remains open between the client and the server, heartbeats will be sent from the server to the client like a ping to check if the connection is still open.
read this wiki to find out more:
http://en.wikipedia.org/wiki/WebSocket

How do i know if connection is alive with websockets?

I have a webapp, which is running in a browser. That webapp is connected to a server, which uses websockets. So the communication between the server and my client/browser is based on websockets. If some magic event occurs on the server, some webservice sends a new XML / JSON to my webapp and the new data gets displayed.
But how do i, as the client / browser, know if the connection is stil alive? Lets say i do not get any new XML for about 30 seconds. How would i know if the connection is closed/broken/server offline or everything is fine, but on the server himself no new magic event occured.
A websocket connection object has a readyState field which will tell you if the connection is still active (from the dart documentation). The readyState can be either
0 - connection not yet established
1 - conncetion established
2 - in closing handshake
3 - connection closed or could not open
You can also define an event handler for the websocket close event if this is something you'd like to handle (try to reconnect, etc).
3 ways:
rely on TCP to detect loss of connectivity, which will ultimately pop up in JS onclose event
send WebSocket pings from server .. browsers will reply with WS pongs, loss of connectivity is probably more robustly detected also on client side
send app level heartbeats from browser to server, server need to have logic to reply. you can't trigger WS pings from browsers (in JS)

Resources