Memory leaks using socket.io - javascript

I've found that sockets are not fully destroyed in socket io server side when manually disconnecting them. I've found this topic on github useful. While I'm looking for some variable-links that prevent GC from cleaning sockets, I'm asking a question here.
If anyone here encountered the same problem, this would be much help.
the code that does not work:
socket.on('disconnect', function(){
socket.removeAllListeners();
});
///...................
socket.disconnect();
Workaround that, however, uses restricted library fields:
delete io.sockets[url];
io.j = [];

actually, this is working as intended, when you disconnect a socket you simply state you're not expecting to receive any more data from that socket right now, to actually destroy the socket you basically do the delete socket action. Use this on the disconnect event, ie:
socket.on('disconnect', function(){
delete socket;
})
you can also do this on the io.sockets.sockets Object on an external function:
function deleteSocket(socketID){
delete io.sockets.sockets[socketID];
}

Related

Detect Websocket close connection when the users close browser?

I am using HTML5 websocket and nodejs in my project to create a simple chat.
Everything works as it should so far.
However, I need to figure out how to detect if the the users that are connected, lost connection somehow and in particular, if they close their browser etc.
I tried the following code.
I can successfully connect like this:
wss.on('connection', function(ws, req) {
//do my stuff here/////
console.log('connection started');
});
However, i cannot see anything in the console when i disconnect by closing the browser.
I use this code to detect connection close:
wss.on('closed', function(ws) {
console.log('connection closed');
});
Could someone please let me know if I am missing something and or doing something wrong?
Thanks in advance.
edit:
This seems to work:
ws.on("close", function() {
console.log("closed");
});
As discussed in this post, the default Websocket implementation doesn't have a way to detect network disconnects, only an intentional disconnect from the user. I recommend that you try to use Socket.IO, as it will do similar what you're looking for, and can detect disconnects. Here's an example:
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('disconnect', () => {
console.log('User disconnected.')
});
The one disadvantage to using Socket.IO is that you'll have to use a JS library on your client instead of using raw WebSockets, but you'll gain the ability to see when a client disconnects.

Check if socket.io server is online from client

I am trying to make a simple socket.io game. I have a login screen, where you enter your username and password, and then you click a big connect button and then you're in (if the client manages to connect to the server). I would like to have a status box on the login screen, so you can see if the server is up or down. I am wondering if there is some sort of ping function in socket.io. Otherwise, could you try to connect to the server (for example, I don't know what's good) 4 times. If it fails, it calls a function/sets a variable, whatever. If it succeeds it calls a function or something, then it disconnects. I have googled around a bit, but can't find anything. (By the way, sorry if this is really noobish, and there is a really apparent solution. I'm new to socket.io 😅) All help will be deeply appreciated!
Socket io has an event listener for this situation. Reconnecting event will fire when socket.io tries to connect but fails. Its a bit misleading cuz it won't fire on every reconnect just when the reconnect try fails.
socket.on('reconnecting', function reconnectCallback(tries) {
if (tries === 3) {
//handle your offline mode here
}
});
socket.on('connect', function connectCallback() {
//handle successful connection here then disconnect
socket.disconnect();
});

Correct way to handle Websocket

I've a client to server Websocket connection which should be there for 40 seconds or so. Ideally it should be forever open.
The client continually sends data to server and vice-versa.
Right now I'm using this sequence:
var socket;
function senddata(data)
{
if (!socket)
{
socket = new WebSocket(url);
socket.onopen = function (evt) {
socket.send(data);
socket.onmessage = function (evt) {
var obj = JSON.parse(evt.data);
port.postMessage(obj);
}
socket.oneerror = function (evt) {
socket.close();
socket = null;
}
socket.onclose = function(evt){
socket = null;
}
}
}
else
{
socket.send(data);
}
}
Clearly as per current logic, in case of error, the current request data may not be sent at all.
To be frank it sometimes gives error that websocket is still in connecting state. This connection breaks often due to networking issues. In short it does not work perfectly well.
I've read a better design : How to wait for a WebSocket's readyState to change but does not cover all cases I need to handle.
Also I've Googled about this but could not get the correct procedure for this.
So what is the right way to send regular data through Websockets which handles well these issues like connection break etc?
An event you don't seem to cover is onclose. Which should work really well, since it's called whenever the connection terminates. This is more reliable than onerror, because not all connection disruptions result in an error.
I personally use Socket.IO, it enables real-time bidirectional event-based communication between client and server.
It is event driven. Events such as
on connection :: socket.on('conection',callback);
and
on disconnect :: socket.on('disconnect',callback);
are built in with socket.io so it can help you with your connection concerns. Pretty much very easy to use, check out their site if you are interested.
I use two-layer scheme on client: abstract-wrapper + websocket-client:
The responsibilities of the websocket-client are interacting with a server, recovering the connection and providing interfaces (event-emitter and some methods) to abstract-wrapper.
The abstract-wrapper is a high-level layer, which interacts with websocket-client, subscribes to its events and aggregating data, when the connection is temporary failed. The abstract-wrapper can provide to application layer any interface such as Promise, EventEmitter and so on.
On application layer, I just work with abstract-wrapper and don't worry about connection or data losing. Undoubtedly, it's a good idea to have here information about the status of connection and data sending confirmation, because it's useful.
If it is necessary, I can provide some code for example
This apparently is a server issue not a problem in the client.
I don't know how the server looks like here. But this was a huge problem for me in the past when I was working on a websocket based project. The connection would continuously break.
So I created a websocket server in java, and that resolved my problem.
websockets depend on lots of settings, like if you're using servlets then servlet container's settings matter, if you're using some php etc, apache and php settings matter, for example if you create a websocket server in php and php has default time-out of 30 seconds, it will break after 30 seconds. If keep-alive is not set, the connection wont stay alive etc.
What you can do as quick solution is
keep sending pings to a server after a certain amount of time (like 2 or 3 seconds, so that if a websocket is disconnected it is known to the client so it could invoke onclose or ondisconnect, I hope you know that there is no way to find if a connection is broken other than failing to send something.
check server's keep-alive header
If you have access to server, then it's timeouts etc.
I think that would help

socket.io 'disconnect' not called if page refreshed fast enough

I have the following abridged code:
io.on('connection', function(client) {
client.uuid = uuid.v4();
// add client object to server...
console.log('socket.io:: client connected ' + client.uuid );
client.on('disconnect', function() {
console.log('socket.io:: client disconnected ' + client.uuid );
// remove client object from server...
});
});
If I open up this page in the browser, everything seems fine. If I refresh the page, it will fire disconnect and then connection. However, if I refresh fast enough, there are times where disconnect doesn't get called and thus client data doesn't get cleaned from the server. Is there any way to protect from this?
Edit: reword reconnect -> connection
As adeneo mentioned, socket.io has heartbeats which automatically check to see if a client is still connected. The disconnect code is fired if it detects the client is actually gone. After replicating my original issue, I tried leaving the server on, and about 30 seconds later, the "dead" clients were being removed. So to solve the issue, you just have to wait. Socket.io takes care of everything on its own.
The same question was answered here.
TL;DR
You can use those options on the client:
const socket = io({
transports: ['websocket'],
upgrade: false
});
This will prevent socket.io from using the HTTP polling method at all, which causes the issues. I used this trick successfully on v4.

socket.io-client object is not a function

I opened a question here earlier (Socket.io trigger events between two node.js apps?), this was much help, but I am confused out of my mind.
I keep getting object is not a function on my client side script.
A little setup, I have a front end site that is served with express localhost:9200 then I have a back end app localhost:3100 that is also served with express and I am trying to emit events from localhost:9200 to the socket.io server localhost:3100
Client script for website localhost:9200
// I have tried many different ways
var socket = io('http://localhost:3100');
var socket = io('http://localhost');
var socket = io();
EDIT
The issue was with the above of course, because io in the above case for some reason was an object when it should be a function, I came across an old post which mentioned using var socket = io.connect('http://localhost:3100'); connect and that worked, I though it was depreciated or something, I have no clue why the docs don't mention this but it fixed my issue.
All result in object is not a function. I include the client side script like this
// tried some different ways
<script src="http://localhost:3100/socket.io/socket.io.js"></script>
<script src="socket.io/socket.io.js"></script> // this is a 404
I have installed https://github.com/automattic/socket.io-client and on the server for the front end website :9200 I have set it up like.
// tried a couple ways to connect
var socket = require('socket.io-client')('http://localhost:3100');
var socket = require('socket.io-client')('http://localhost');
socket.on('connect', function(){});
socket.on('event', function(data){});
socket.on('disconnect', function(){});
I am confused on how to properly configure this so that I can get my site to emit socket events to my server and visa versa?
Well I figured it out, this is pretty ridiculous but on the client side javascript I needed to add var socket = io.connect('http://localhost:3100'); the io.connect made it work versus var socket = io('http://localhost:3100');
Maybe I missed it but the docs don't say to use io.connect https://github.com/automattic/socket.io-client whatever it works and I am happy, any thoughts on why the docs don't mention this would be great.
The difference is io.connect is pre 1.0 syntax. They changed it for whatever reason. These are the exact kind of fun surprises I have come to expect in socket.io.

Categories

Resources