How to keep a socket.io connection alive - javascript

OK let's say I have a simple server set up like this:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var lobby = io.of('/lobby');
lobby.on("connection", function (socket) {
console.log("Successful connection lobby");
socket.on("disconnect", function () {
console.log("Successful disconnect lobby");
});
});
I have noticed that if a user just stays plugged into the system they are eventually dropped. I thought I could do something with the namespace, where I use a chron job, on a 5 minute interval, to do lobby.emit('ping') and all the clients connected would have an
.on('ping', new Emitter.Listener() {
#Override
public void call(Object... args) {
lobby.emit('pong');
}
});
and the server would have a .on('pong', function() {}); that effectively is a blank function. Is there another/better way to keep the system from timing out people who are not active?

Related

Using Socket.IO from Node.js to connect to external server

Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.
I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.
Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.
var myemail = "email#gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.
var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables
var myemail = "email#gmail.com";
var device_id = '12345';
var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');
//Connect listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
Any ideas?
UPDATE
Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).
debugging output image link
Solved this - issue was that the server I was connecting to required use of https, so I needed to add
{secure: true, rejectUnauthorized: false}
after the url to connect to.
Full working example:
const myemail = email#email.com;
const device_id = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true, rejectUnauthorized: false});
function doStuff(){
//Listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "003021");
}
doStuff();
I think the line causing the issue is :
var socket = io.connect('https://example.net:3000');
I managed to make a working example using this code :
const myemail = "email#gmail.com";
const device_id = '12345';
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
try{
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
}catch(e){ console.log(e); }
});

Match websocket with http request when user connects

The issue that I'm having is http request happen independently or at different time as a web socket connection. The idea is that when a user connects I can store a session id and a web socket within the same pair in var allConnectionsMatches = [];and use this information later in a post request to find out which socket is calling the request so I can emit to that particular socket. The code below shows my attempt. What I wrote does work to an extent but It has a few issues such as when you refresh it sometimes doesnt emit messages anymore, or when you exit out the browser and connect again there is no message emitted by socket io. Any ideas?
var allConnectionsMatches = [];
var sessionID;
app.get('/', function(req, res, next) {
sessionID = req.session.id;
res.render('index.ejs')
});
function findDuplicates(data, sessionID, socket) {
var isPositive = data.lastIndexOf(sessionID);
if (isPositive === true) {
var socketLocation = allConnectionsMatches.indexOf(sessionID);
socketLocation + 1;
allConnectionsMatches.splice(socketLocation, 1, socket)
} else if(isPositive === -1) {
data.push(sessionID, socket);
} else {
}
}
io.sockets.on('connection', function (socket) {
findDuplicates(allConnectionsMatches, sessionID, socket)
});

Socket IO - Socket.emit is sent to all clients

I am creating a game using socket io. A player connects like this:
var playerName = document.getElementById("name").value;
socket.emit('setup player', {
name : playerName
});
Then on the server, the player is setup and his information is sent back to the client:
function onSetupPlayer(data) {
...
var newPlayer = new Player(x, y, color, data.name,
this.id, scale);
socket.emit('setup game', {
localPlayer : newPlayer
});
...
sockets[this.id] = socket;
}
The following call:
socket.emit('setup game', {
localPlayer : newPlayer
});
Should send the setup data only back to the client that requested the setup to be done originally. However the setup call gets send to everyone in the lobby.
Could this have anything to do with the fact that I am using localhost to test it? I am also testing it on the same machine by using different tabs. If this is what is causing the issue, is there a way to resolve it? Since this is pretty annoying when testing my game.
EDIT:
Initialization:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var socket = require('socket.io')(http);
var path = require('path');
var io = require('socket.io')(80);
...
var setEventHandlers = function() {
socket.sockets.on("connection", onSocketConnection);
};
Listening for connection:
function onSocketConnection(client) {
...
client.on("setup player", onSetupPlayer);
...
};
And on the client side I have this:
var setEventHandlers = function() {
socket.on("setup game", onSetupGame);
...
}
socket.emit send event to everyone excepts this. To send data back to this user try
io.to(socket).emit()

When can be socket client disconnected

please look at the code below. It's a simple program in nodeJS.
Question is why disconnect is not printed? (If you uncomment setTimeout, problem is gone)
What is the real question?: Why can't I start socketIO client and server together and close a socket immediately after connection? What is the know-how regarding connections with socketIO?
"use strict";
var Promise = require("bluebird");
var socketio = require("socket.io");
var socketio_client = require("socket.io-client");
var http = require("http");
var port = 7457;
var hostandport = "http://localhost:" + port.toString();
var server = socketio.listen(port);
var client = socketio_client(hostandport);
server.sockets.on("connect", function (socket) {
console.log("connect");
socket.on("disconnect", function () {
console.log("disconnect");
});
//setTimeout(function() {
client.disconnect();
//}, 1000);
});
You have set up your server incorrectly, do this instead:
var server = require('http').createServer(handler);
var io = require('socket.io')(server);
io.on("connect", function (socket) {
console.log("connect");
socket.on("disconnect", function () {
console.log("disconnect");
});
//More importantly, you have done this part wrong,
//the rest of your code may be functional,
//but it does not adhere to what socket.io sets out in its own API
//(http://socket.io/docs/)
socket.disconnect();
});
In Socket.io there is no such thing as connection on server side and/or browser side. There is only one connection. If one of the sides closes it, then it is closed. So you can close it from Server using socket.disconnect()
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
setTimeout(function() {
socket.disconnect();
}, 1000);
});
Goto http://socket.io/get-started/chat/ for more clarifications.

Socket.IO not using fallback methods

I have a node server that's running a socket.io server and a client to work with it. Simple story, I need to be able to transfer messages between the two. This is working as intended in browsers that support web sockets but when a fallback method needs to be used its not working.
I should mention that pages are served from an apache server and the node server is only used for a specific page. The code that I am using is below, I've tinkered on this for a while and can't figure out how to fix it.
Also worth mentioning that when the page is opened in IE9(websockets not supported),
logging connection.io.engine.transport.name would give "websocket".
Client:
connection = io(window.location.protocol + '//localhost:8888', {
'reconnect': false,
'max reconnection attempts': 0,
'transports':
[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]
});
connection.on('connect',function () {
console.log("Socket is open");
$('#dc-status').hide();
connection.emit('message',JSON.stringify(info));
connection.on('message',function (e) {
//DO SOMETHING WITH THE DATA RECIEVED
});
});
Server:
var ioserver = require('socket.io');
var io = ioserver.listen(8888);
var http = require("http");
console.log("server started...");
io.set('transports',[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);
io.sockets.on('connection', function(ws) {
var req;
var order;
var courier;
var after;
var session;
var options = {};
console.log("New client connected");
// console.log("Transport: " + io.transports[ws.id].name);
ws.on('message', function(data) {
//WORK WITH THE DATA RECEIVED
//NOT RELEVANT TO EXAMPLE
console.log('received: %s', data);
parsedData = JSON.parse(data);
});
ws.on('disconnect', function () {
console.log("Connection closed");
});
});
Ok, so after much struggle with this I have found a solution for making sockets work in old browsers.
As of version 1.0 Socket.io uses Engine.io instead of fallback methods, which takes care of transports.
To get a working solution I skipped using the Socket.io layer and used just Engine.io instead.
In the client you have something like
var connection = eio.Socket('host-address');
and then you just bind the regular events(e.g message, close).
And in the server part instead of require('Socket.IO'), you call require('Engine.IO'), example:
var engineio = require('engine.io');
var wss = engineio.listen(10101);
The binding is the same.

Categories