SockJS Client auto reconnect? - javascript

I'm trying to figure out a way for my SockJS clients to reconnect to the server if it should go down.
I currently have this:
new_conn = function() {
socket = new SockJS(protocol + serverDomain + '/echo', null, {
'protocols_whitelist': ['websocket', 'xdr-streaming', 'xhr-streaming', 'iframe-eventsource', 'iframe-htmlfile', 'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling']
});
};
socket.onopen = function () {
clearInterval(recInterval);
};
socket.onclose = function () {
recInterval = window.setInterval(function () {
new_conn();
}, 2000);
};
The problem is that the setInterval keeps firing even after a successful reconnect. It seems that the socket.onopen never gets executed.
Any ideas what I could be doing wrong?

I think it could be related to variable scoping. Try this:
var recInterval = null;
new_conn = function() {
socket = new SockJS(protocol + serverDomain + '/echo', null, {
'protocols_whitelist': ['websocket', 'xdr-streaming', 'xhr-streaming', 'iframe-eventsource', 'iframe-htmlfile', 'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling']
});
};
socket.onopen = function () {
clearInterval(recInterval);
};
socket.onclose = function () {
recInterval = window.setInterval(function () {
new_conn();
}, 2000);
};
Anyway, it's strange, because you were declaring recInterval on the window object, and it should have worked. If it doesn't work, you could also debug it with a browser, with debugger; statements or interactively by setting local breakpoints... (in onopen, for example).
By the way, I rewrited the whole code like this (I like refactoring:):
var recInterval = null;
var socket = null;
var new_conn = function() {
socket = new SockJS(protocol + serverDomain + '/echo', null, {
'protocols_whitelist': ['websocket', 'xdr-streaming', 'xhr-streaming',
'iframe-eventsource', 'iframe-htmlfile',
'xdr-polling', 'xhr-polling', 'iframe-xhr-polling',
'jsonp-polling']
});
socket.onopen = function () {
clearInterval(recInterval);
};
socket.onclose = function () {
recInterval = setInterval(function () {
new_conn();
}, 2000);
};
};

In case anyone still interested in this topic: The refactored code snippet from franzlorenzon causes a lot of reconnects since it is kind of recursive reconnecting itself somehow since each two seconds a new onclose event is spawned (regardless of the recInterval).
Moving the clear interval right after the socket creation does the trick. I also added a socket = null in the onclose event.
var recInterval = null;
var socket = null;
var new_conn = function() {
socket = new SockJS(protocol + serverDomain + '/echo', null, {
'protocols_whitelist': ['websocket', 'xdr-streaming', 'xhr-streaming',
'iframe-eventsource', 'iframe-htmlfile',
'xdr-polling', 'xhr-polling', 'iframe-xhr-polling',
'jsonp-polling'
]
});
clearInterval(recInterval);
socket.onopen = function() {
};
socket.onclose = function() {
socket = null;
recInterval = setInterval(function() {
new_conn();
}, 2000);
};
};

Related

TryCatch with Websocket on two IPs is not handled in javascript

I have a websocket listening on some interfaces so the client could call more than one ip. I don't have a dns for these IPs. This failes even in the try block
window.onload = function() {
ws = "";
try {
ws_connection = "ws://" + lblInfoIP.value + ":9080/websockets";
ws = new WebSocket(ws_connection);
}
catch(err) {
ws_connection = "ws://127.0.01:9080/websockets";
ws = new WebSocket(ws_connection);
}
ws.onmessage = function(msg) { showInfo(msg.data); };
ws.onerror = function(evt){ alert ('Websocket failed with ' + evt.data) };
}
manually using the same ip as the called url works.
How would I correctly handle that ?
Is there somesthing like ws_connection = "ws://" + called_url + "/websockets"; ?
Instead of your try/catch construct, use a simple "or" (||) operation:
window.onload = function () {
let ws = new WebSocket(`ws://${lblInfoIP.value || "127.0.01:9080"}/websockets`)
ws.onmessage = function (msg) { showInfo(msg.data); };
ws.onerror = function (evt) { alert('Websocket failed with ' + evt.data) };
}
In development, set lblInfoIP.value to null or "undefined".
Or use "document.location.host:9080"

Server to server Socket IO messaging

Context:
Node.js running a server with require("socket.io");
Node.js running another server with require("socket.io-client");
Receiving acknowledgements (from the other server) when using the standard :
io.on("connection", function() { console.log("Something connected."); });
Problem:
Unfortunately, I cannot get the CLIENT on either server both are running client & server socket.io to emit a message to the server of the other.
I realize it's probably a code error, so I'll include that for correctness' sake, but for the record I'm wondering if there's something I'm doing wrong semantically as opposed to code-wise.
Code: (LoginServer.js)
var app = require('http').createServer();
var io = require('socket.io')(app);
var ioc = require("socket.io-client");
var LoginServer = (function() {
function LoginServer() {
this.gameServerSocket = ioc.connect("http://localhost:3031", {reconnect: true});
}
LoginServer.prototype.initialize = function() {
var self = this;
io.listen(3032);
io.on("connection", function(socket) {
socket.emit("connection");
});
this.gameServerSocket.on("connection", function() {
console.log("Game Server Connected!");
self.gameServerSocket.emit("login", {accountName: "default"});
});
}
return LoginServer;
})();
exports.LoginServer = LoginServer;
Code: (GameServer.js)
var app = require('http').createServer();
var io = require('socket.io')(app);
var ioc = require("socket.io-client");
var GameServer = (function() {
function GameServer() {
this.loginServerSocket = ioc.connect("http://localhost:3032", {reconnect: true});
this.loginServerSocket.emit("connection");
}
GameServer.prototype.initialize = function() {
var self = this;
io.listen(3031);
io.on("connection", function(socket) {
socket.emit("connection");
});
this.LoginServerResponses();
}
GameServer.prototype.LoginServerResponses = function() {
var self = this;
this.loginServerSocket.on("connection", function() {
console.log("Login Server Connected!");
});
this.loginServerSocket.on("login", function(data) {
console.log("Login Server:", data);
});
}
return GameServer;
})();
exports.GameServer = GameServer;
After doing some more testing, I realized your code is working fine. Maybe you're calling your modules incorrectly? I used this as my index.js and the two server-client pairs connected fine:
// index.js
var GameServer = require('./GameServer.js').GameServer;
var LoginServer = require('./LoginServer.js').LoginServer;
var lserver = new LoginServer();
var gserver = new GameServer();
lserver.initialize();
gserver.initialize();
Side note on sockets
I believe you can accomplish what you want to do with only 1 stream between the login and game servers. Here a redo of your code using only 1 server and 1 client that does the same thing:
GameServer.js:
var http = require('http');
var io = require('socket.io');
function GameServer() { }
GameServer.prototype.initialize = function() {
var self = this;
self.httpServer = http.createServer();
self.ioServer = io(self.httpServer);
self.ioServer.listen(3031);
self.ioServer.on("connection", function(socket) {
socket.emit("connection");
});
this.LoginServerResponses();
}
GameServer.prototype.LoginServerResponses = function() {
var self = this;
this.ioServer.on("connection", function() {
console.log("Login Server Connected!");
});
this.ioServer.on("login", function(data) {
console.log("Login Server:", data);
});
}
exports.GameServer = GameServer;
LoginServer.js:
var ioc = require("socket.io-client");
function LoginServer() {
this.gameServerSocket = ioc.connect("http://localhost:3031", {reconnect: true});
}
LoginServer.prototype.initialize = function() {
var self = this;
self.gameServerSocket.on("connection", function() {
self.gameServerSocket.emit("connection");
});
this.gameServerSocket.on("connection", function() {
console.log("Game Server Connected!");
self.gameServerSocket.emit("login", {accountName: "default"});
});
}
return LoginServer;
exports.LoginServer = LoginServer;
"Unfortunately, I cannot get the CLIENT on either server both are running client & server socket.io to emit a message to the server of the other."
What you really want to do is 1 server, and allow clients to connect.
The server can communicate to the clients, so does the clients to the server, back and forth.
server.js
var app = require('http').createServer();
var io = require('socket.io')(app);
io.listen(3032);
io.on('connection', function(socket) {
console.log('A user(a client) connected!');
// lets welcome this particular client with a nice msg :)
socket.emit('msg group', 'Welcome client! you can emit msgs for me to tell every client in "to everyone please"');
// lets tell everyone someone joined
io.emit('msg group', 'guys someone special joined :)!');
socket.on('to everyone please', function(freedomMsg) {
io.emit('msg group', "a client told me (the server) to send this to everyone (every clients)!: " + freedomMsg);
});
});
aClient.js
var ioc = require("socket.io-client");
var socket = ioc("http://localhost:3032");
// general chat
socket.on('msg group', function(msg) {
console.log(msg);
});
function msgEveryone(message) {
socket.emit('to everyone please', message);
}
msgEveryone('whats up guys?');
I hope that with this you'll understand a bit more on how socket.io (or sockets in general) works :)
Code: (GameServer.js)
first delete these code :
this.loginServerSocket.on("login", function(data) {
console.log("Login Server:", data);
});
second change code:
GameServer.prototype.initialize = function() {
var self = this;
io.listen(3031);
io.on("connection", function(socket) {
socket.emit("connection");
});
this.LoginServerResponses();
}
to
GameServer.prototype.initialize = function () {
var self = this;
io.listen(3031);
io.on("connection", function (socket) {
socket.emit("connection");
socket.on("login", function (data) {
console.log("Login Server:", data);
});
});
this.LoginServerResponses();
}
Try this:
LoginServer.js
var app = require('http').createServer();
var io = require('socket.io')(app);
var ioc = require("socket.io-client");
var LoginServer = (function() {
function LoginServer() {
this.gameServerSocket = ioc.connect("http://localhost:3031", {reconnect: true});
}
LoginServer.prototype.initialize = function() {
var self = this;
io.listen(3032);
io.on("connection", function(socket) {
// a client, maybe game server, is connected
socket.on("login", function(data){ console.log("Credentials: "+ data); });
});
this.gameServerSocket.on("connect", function() {
console.log("Connected to Game Server!");
// Send event to game server
});
}
return LoginServer;
})();
exports.LoginServer = LoginServer;
GameServer.js
var app = require('http').createServer();
var io = require('socket.io')(app);
var ioc = require("socket.io-client");
var GameServer = (function() {
function GameServer() {
this.loginServerSocket = ioc.connect("http://localhost:3032", {reconnect: true});
}
GameServer.prototype.initialize = function() {
var self = this;
io.listen(3031);
io.on("connection", function(socket) {
// a client, maybe login server, is connected
});
this.LoginServerResponses();
}
GameServer.prototype.LoginServerResponses = function() {
var self = this;
this.loginServerSocket.on("connect", function() {
console.log("Connected to Login Server !");
// Try to login
self.loginServerSocket.emit("login", {accountName: "default"});
});
}
return GameServer;
})();
exports.GameServer = GameServer;

OnMessage event never getting called - Websockets client (javascript)

I am having trouble writing a client to establish a web socket connection. The client successfully establishes a connection but when the server sends data the OnMessage event never gets triggered. I am using OWIN Websocket Extension for my server side portion.
Server
dynamic data = fillData(value);
string sendInfo = Newtonsoft.Json.JsonConvert.SerializeObject(data);
byte[] infoBytes = System.Text.Encoding.UTF8.GetBytes(sendInfo);
await sendAsync(new ArraySegment<byte>(infoBytes), 1, false, pair.Key.callCancelled);
Client
try {
url = "wss://localhost/piwebapi/elements/E0DqD5loBNH0erqeqJodtALA2U5w0WX-5BGAupiQlq51PAUkVTVFVOSVRcU1VHQVJNQU5cU0FNUExFIEVMRU1FTlQ/attributes";
socket = new WebSocket(url);
socket.onopen = function (openEvent) {
document.getElementById("serverStatus").innerHTML =
'WebSocket Status:: Socket Open';
document.getElementById("destination").innerHTML =
url;
};
socket.onmessage = function (messageEvent) {
if (messageEvent.data instanceof Blob) {
var destinationCanvas = document.getElementById('destination');
var destinationContext = destinationCanvas.getContext('2d');
var image = new Image();
image.onload = function () {
destinationContext.clearRect(0, 0,
destinationCanvas.width, destinationCanvas.height);
destinationContext.drawImage(image, 0, 0);
}
image.src = URL.createObjectURL(messageEvent.data);
} else {
document.getElementById("serverResponse").innerHTML =
'Server Reply:: ' + messageEvent.data;
}
};
socket.onerror = function (errorEvent) {
document.getElementById("serverStatus").innerHTML =
'WebSocket Status:: Error was reported';
};
socket.onclose = function (closeEvent) {
document.getElementById("serverStatus").innerHTML =
'WebSocket Status:: Socket Closed';
};
}
catch (exception) { if (window.console) console.log(exception); }
The OnOpen and OnClose work just fine but somehow the OnMessage never gets triggered, any ideas?
Edit - Sending data from client to server works as well.

Node JS and Socket IO

I'm trying to write an object with member functions for receiving and sending data to and from the client with Node JS and Socket IO. The problem is that every time I send data from the client, there is a new 'connection' event that fires. Is that how it works? I thought the connection event would only occur on a new connection. So with the code below, the log echoes 'New connection' with every reception from the client. It doesn't seem right.
io.sockets.on('connection', function (socket) {
console.log('New connection');
var localSocket = socket;
var newsock = new UserSocket(localSocket);
newsock.game = null;
newsock.host = null;
newsock.opponent = null;
newsock.room = "";
newsock.SendToHostSocket('Welcome to Baseball Strategy II');
arrSockets.push(socket);
});
function UserSocket(sock) {
var localSock = sock;
var o = this;
this.sock = localSock;
this.sock.on('clientData', function (data) {
console.log("user socket object");
console.log(o);
o.ParseClientData(data);
});
}
This is a simplified version of what I have for the client:
$(document).ready( function () {
var socket = io.connect('http://local.baseball.com:3333');
function SocketGameOut(outstring) {
socket.emit('clientData', outstring );
}
$("#hostGame").click( function () {
var gamenum = $('input[name=gameSelect]:checked', '#gameForm').val();
var aSendData = { command : "newgame" , senddata : { gameid : gamenum } };
var senddata = JSON.stringify(aSendData);
SocketGameOut(senddata);
});
});
Modify your code as below it worked for me.
//use once.('connection') instead of on.('connection')
io.sockets.once('connection', function (socket) {
console.log('New connection');
var localSocket = socket;
var newsock = new UserSocket(localSocket);
newsock.game = null;
newsock.host = null;
newsock.opponent = null;
newsock.room = "";
newsock.SendToHostSocket('Welcome to Baseball Strategy II');
arrSockets.push(socket);
});

Public methods in javascript OOP

I want to make a javascript class with methods which I can call within the class as well as outside of the class. I want to make a "public" method, if you will. I want getTextAreaElement and appendTextArea to be such methods.
I've shown a snippet of best code I could come up with so far. I've also tried defining the methods as prototypes as well as within the class (this.func = ...). But that only allowed me to call the method outside (new Socket().appendTextArea("osgjr89");) but NOT within the class itself! The code snippet below shows the exact opposite implementation where I can't call the method outside of the class but can call it within.
Error:
Uncaught TypeError: Object #Socket has no method 'appendTextArea'
socket.js:
function Socket() {
var socket;
var canvas = document.getElementById('c');
var context = canvas.getContext("2d");
if (window.WebSocket) {
socket = new WebSocket("ws://localhost:9012/websocket");
socket.binaryType = 'arraybuffer';
socket.onopen = onopen;
socket.onmessage = onmessage;
socket.onerror = onerror;
socket.onclose = onclose;
} else {
alert("Your browser does not support Web Socket.");
}
function getTextAreaElement() {
return document.getElementById('responseText');
}
function appendTextArea(newData) {
var el = getTextAreaElement();
el.value = el.value + '\n' + newData + " :)";
}
function onopen(event) {
getTextAreaElement().value = "Web Socket opened!";
}
/*[...]*/
}
main.js (loads after socket.js)
$(document).ready(function() {
var s = new Socket();
s.appendTextArea("osgjr89"); // ERROR!
});
UPDATED socket.js:
function Socket() {
[...]
if (window.WebSocket) {
socket = new WebSocket("ws://localhost:9012/websocket");
socket.binaryType = 'arraybuffer';
socket.onopen = this.onopen;
socket.onmessage = this.onmessage;
socket.onerror = this.onerror;
socket.onclose = this.onclose;
} else {
alert("Your browser does not support Web Socket.");
}
this.getTextAreaElement = function() {
return document.getElementById('responseText');
}
this.appendTextArea = function(newData) {
var el = this.getTextAreaElement();
el.value = el.value + '\n' + newData + " :)";
}
this.onopen = function(event) {
this.getTextAreaElement().value = "Web Socket opened!";
}
[...]
}
All public methods must be declared as properties, not variables/functions. So, you have to change stuff like this:
function getTextAreaElement() {
return document.getElementById('responseText');
}
into
this.getTextAreaElement = function() {
return document.getElementById('responseText');
}
If you do this.func = function() {}, you can call the function inside the Constructor (Socket in your case) using this.func() as well as outside using:
var s = new Socket();
s.func();

Categories

Resources