Using Socket.io, connections keep dropping - node.js

I'm using Socket.io to do some communication between a phone and a web page, and I'm having issues with the server constantly dropping connections. I've seen a lot of other people posting about Socket.io where their connections drop after being idle for about 5 minutes or so, but this is a connection that has constant information being emitted back and forth, and the longest I've been able to maintain a connection is about 30 seconds.
The server side code I'm running is:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('create', function (room) {
socket.join(room);
});
socket.on('player-move', function(msg){
roomId = msg['room'];
move = msg['action'];
socket.broadcast.to(roomId).emit('player-move', move);
});
socket.on('disconnect', function() {
console.log('someone has disconnected');
});
});
http.listen(443, function(){
console.log('listening on *:443');
});
The client side is pretty basic emit events. Here's an example:
$( "#arrow-left" ).on( "touchstart", function(){
var senddata = { "room": roomId, "action": "d-l" };
socket.emit( "player-move", senddata );
});
Everything seems to be running fine until 5-30 seconds after everything starts and then the connection just drops. The connection usually starts up again, but after 5-10 seconds. Has anyone had similar issue occurring? Would this potentially be an issue with the server rather than the code? I've done similar things before on different servers with Socket.io and haven't had this kind of connection issue. Any help or direction to go in would be appreciated. Thanks!

I had the same problem with another library called ws and I tried to handle the disconnection method properly by deleting the specific client sending the disconnection request from a array of clients. I don't exactly know how, but it solved my problem.
clients = []
io.on('connection', function(socket){
clients.push(socket);
// above methods
socket.on('disconnect', function(){
console.log("disconnected");
deleteFromArray(clients, socket.id);
});
});
function deleteFromArray(arr, element) {
position = arr.indexOf(element);
arr.splice(position, 1);
}

Related

How to create multiple Nodejs socket io server-client?

I am new to Nodejs and Socket.io, and this is first time when I am creating any chat application, so pardon me if I am asking some silly question.
In my web I have to kind of chat services, one is Live debate which is kind of chat room, and another one is private messaging like Facebook Messenger.
I have created both, in private messenger before showing the message I am checking the conversation Id, it's working quite appropriately. Live debate is also working appropriately.
But there is a issue, any message sent in private messenger displays in live debate window also. So I change the Server.js file for messenger and also changed the listening port, now the listening port for live debate is 3000 and for messenger is 8050, but still Live debate receiving the messenger messages.
Am I doing this in wrong way? Is there any other way to run two chat applications ?
I am using this server code
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
server.listen(3000);
io.on('connection', function (socket) {
console.log("client connected");
var redisClient = redis.createClient();
redisClient.subscribe('message');
redisClient.on("message", function(channel, data) {
console.log("mew message add in queue "+ data+ " channel");
socket.emit(channel, data);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
With using Namespace
server.js
var nsp = io.of('/debate')
nsp.on('connection', function (socket) {
console.log("client connected"+socket.id);
var redisClient = redis.createClient();
redisClient.subscribe('message');
var redisClient1 = redis.createClient();
redisClient1.subscribe('debate');
redisClient.on("message", function(channel, data) {
console.log("mew message add in queue "+ data+ " channel");
nsp.emit(channel, data);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
client code
var socket = io.connect('http://localhost:3000/debate');
socket.on('message', function (data) {
data = jQuery.parseJSON(data);
console.log(data.user);
$( "#messages" ).append( "<strong>"+data.user+":</strong><p>"+data.message+"</p>" );
$('#messages').animate({
scrollTop: $('#messages').get(0).scrollHeight}, 200);
});
socket.io supports the use of different namespaces. You should use that feature instead of creating two individual servers. After that you can use socket.emit to that specific namespace. For more information see the documentation: https://socket.io/docs/rooms-and-namespaces/
It's not too difficult, I wrote a chat app, as I think everyone does when they start nodejs, but nodeJS has rooms which are quite easy to use.
io.on('connection', function(client){
client.on('room_connection', function(id){
client.join(id); // User joins room.
})
client.on('message', function(data){
io.to(data.room).emit('message', {message:data.message, client:client.conn.id});
});
})
This is pretty much all you need. This works for PM's since u simply won't allow multiple users to join this chatroom, and normal chatrooms which multiple users can join.

Socket io namespace server emit three times to client

Hi i have been looking through questions here on why my socket io server is emitting three times to the client.
DISCLAIMER: this is not a duplicate question, please view my issue carefully
This is how i bind the server to express
var server = http.createServer(app);
var io = require('socket.io').listen(server);
//var io = require('socket.io')(http);
require('./routes/sock')(io);
//server.listen(port);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
Now this is how i listen in my routes/sock file, i simply create a namespace and start listening for events
module.exports = function (io) {
var chat = io.of('/chat');
chat.on('connection', function (cs) {
console.log('User Connected to chat');
// save client id
var socketid = cs.id;
chat.setMaxListeners(0);
cs.on('my message', function (event) {
chat.to(socketid).emit('my message', 'for your eyes only');
});
cs.on('second message', function (event) {
chat.to(socketid).emit('second message', 'for your eyes only');
});
cs.on('third message', function (event) {
chat.to(socketid).emit('third message', 'for your eyes only');
});
.....
//other events follow with the same flow
})
}
Analysis
On the client side, i have logs and the client is emitting only once,
However when the server responds it emits three times to the client, making the client listener fire three times
What am i doing wrong?
This is not a duplicate question please, no one is having the same issues with namespaces.
Update, there wasn't anything wrong with my socket server, the problem was on my client side android, my client could listen more than once, it's in the android Activity lifecycle. Basically my android developer told me that he called the listener in the onResume and onPause which made it listen twice. Anyway am not an android developer, i just hope no one gets the same issue.

Nodejs request proxy stream(mjpeg) connection never ends

(unnecessary backstory)
I have a nodejs server with expressjs framework that's proxy streaming a webcam feed. The reason I need this is because the mjpg stream must come from this server due to complex CORS issues.
//proxy from webcam server to avoid CORS complaining
app.get('/stream1',function(req,res){
var url="http://camera.nton.lviv.ua/mjpg/video.mjpg"
request(url).pipe(res);
});
question :
The issue is simple. request(url).pipe(res) never closes, because the source is mjpeg which literally never ends. I need to find a way to force close this pipe when the client(browser; the destination) is no longer available - as in, closes the window.
The other answers did not work for me.
This line var pipe=request(url).pipe(res);
returns the pipe instead of the request object. So I needed to break the line up.
The request object is needed to abort. Calling the .end() didn't work either, but the .abort() did the trick. It took me hours to find the answer that worked for me, so I thought I would share.
app.get('/cam/frontdoor',function(req,res){
var request_options = {
auth: {
user: '',
pass: ''},
url: 'http:/xx.xx.xx.xx/mjpg/video.mjpg',
};
var req_pipe = request(request_options);
req_pipe.pipe(res);
req_pipe.on('error', function(e){
console.log(e)
});
//client quit normally
req.on('end', function(){
console.log('end');
req_pipe.abort();
});
//client quit unexpectedly
req.on('close', function(){
console.log('close');
req_pipe.abort()
})
})
Use socket.io to monitor the remote connection
// install it on your project
npm install socket.io
// require it on server side
var socket = require('socket.io');
// listen for sockets from your server
var mysocks = socket.listen(myexpressappvar);
// keep collection of sockets for use if needed
// its good practice
var connectedSockets = [];
// add event handelers on server side
mysocks.sockets.on("connection", function(socket){
// add socket to our collection
connectedSockets.push(socket);
// you will need to bind their stream id here.
exe.....
// listen for disconnected
socket.on("disconnect", function(){
// remove socket from collection
connections.splice(connections.indexOf(socket), 1);
// destory stream here
exe...
});
});
// last thing, is add socket.io to the client side.
<script src="/socket.io/socket.io.js"></script>
// then call connect from client side js file
var socket = io.connect();
I have found out a simpler way. Add a event listener for client connection closing, and force close the pipe when it happens.
app.get('/stream1',function(req,res){
var url="http://camera.nton.lviv.ua/mjpg/video.mjpg"
var pipe=request(url).pipe(res);
pipe.on('error', function(){
console.log('error handling is needed because pipe will break once pipe.end() is called')
}
//client quit normally
req.on('end', function(){
pipe.end();
}
//client quit unexpectedly
req.on('close', function(){
pipe.end();
}
});

Node.js + Socket.io + Redis app via PM2 with large memory footprint

I'm new to both node.js and socket.io, but I'm trying to build a simple service that listens to Redis notifications (fed by PHP app), and broadcasts them to any users currently logged in, connected to a socket.io room e.g. 'site_name:user:user_id'.
I have it working, but the memory footprint of the Node app quickly gets larger and larger, going from 100mb to 200+mb pretty quickly with about 100 users online and actively browsing, and I'm wondering if I have something set up wrong here.
PM2 is handling the node app, and nginx is set up as reverse proxy.
Server side:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
var redisClient = redis.createClient();
var allClients = [];
server.listen(8890);
io.sockets.on('connection', function (socket) {
allClients.push(socket);
socket.on('subscribe', function(data) {
console.log('Joining room', data.room);
socket.join(data.room);
redisClient.subscribe(data.room);
})
socket.on('disconnect', function() {
console.log('Disconnect');
var i = allClients.indexOf(socket);
delete allClients[i];
});
});
// Watch for connection errors and log
redisClient.on('error', function (err) {
console.log('Error event - ' + redisClient.host + ':' + redisClient.port + ' - ' + err);
});
redisClient.on('message', function(room, message) {
console.log('New message: ' + message + '. In room: ' + room);
io.sockets.in(room).emit('message', message);
});
Client side:
// connect to socket
socket = io.connect('http://localhost:8890');
// subscribe to user's room once connected
socket.on('connect', function(data){
socket.emit('subscribe', { room: site_name + ':user:' + user_id });
});
// show messages from user's "room" via redis notifications
socket.on('message', function (response) {
var json = new Hash(JSON.decode(response, true) || {});
roar.alert(json.title, json.message, { link: json.link });
});
Seems like this should be a very lean app, no? What's a normal memory footprint for a simple node.js app?
The server starts up at 41mb, but even without anybody connecting to it, memory creeps up slowly, about 1mb a minute. Once I start connecting users, it bloats up quickly to 200+mb until I kill it.
I'm not clear on how best to handle the redisClient and socket connections as users connect & disconnect, and I thought that might be the issue. But seeing it creep up while idle is disconcerting.
PM2 v0.15.7
node v0.12.7
socket.io v1.3.7
express v4.13.3
nginx v1.6.2
Any help much appreciated.
I have a similar setup although it is not released and have done no stress testing yet... but here is an idea for you:
Use the redis module for socketio (whether it is any better then the redisClient would be interesting to know). It uses a different client for pub'ing and sub'ing. The subClient uses detect_buffers.
var redisModule = require('socket.io-redis');
var redisAdapter= redisModule({
host: redisClient.options.host
, port: redisClient.options.port
, pubClient: redisClient
//, subClient: ... separate client that uses detect_buffers
});
io.adapter(redisAdapter);
then subscribe/disconnect looks like this:
socket.on('subscribe', function(room) {
socket.join(room);
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
I've also read multiple times that at one point socketio was not the best and to instead use sockjs. No idea if that is still the case.
And... since I just realized it's been more than 2 months. Did you find anything to reduce your memory footprint?

Node js - Socket.io-client is not connecting to socket.io server

I am trying to connect to a socket.io-client using the following code:
Server:
// Load requirements
var http = require('http'),
io = require('socket.io');
// Create server & socket
var server = http.createServer(function(req, res){
// Send HTML headers and message
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('<h1>Aw, snap! 404</h1>');
});
server.listen(8080);
io = io.listen(server);
// Add a connect listener
io.sockets.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
Client:
console.log('1');
// Connect to server
var io = require('socket.io-client')
var socket = io.connect('localhost:8080', {reconnect: true});
console.log('2');
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected!');
});
console.log('3');
I don't get the Connected console log or Client Connected console log and I don't know why! The code sample is taken from another question posted: Link and I don't see any solution to the problem...
Use the same version of socket io client and server. It will work perfectly.
Also you need to add protocol with path.
change
var socket = io.connect('localhost:8080', {reconnect: true});
to
var socket = io.connect('http://localhost:8080', {reconnect: true});
Assuming you are using a socket.io version greater than 1.0, on the server, change this:
// Add a connect listener
io.sockets.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
to this:
// Add a connect listener
io.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
See the socket.io documentation reference here.
You don't want to be listening for this event only on already connected sockets. You want to listen for this event on any socket, even a newly created one.
Also, be very careful when reading socket.io code in random places on the internet. Some things changed significantly from v0.9 to v1.0 (I don't know if this was one of those things or not). You should generally always start with the socket.io documentation site first since that will always represent the latest version. Then, if looking at other internet references, make sure you only use articles that are later than mid-2014. If you don't know the vintage of an article, it's best not to rely on it without corroboration from a more recent article.
you can use localhost. It works for me as well. You must use your ip address and port that works for you

Resources