SOCKJS client - Detect server is unreachable - javascript

I'm using vertxbus that internally built upon sockjs and I have a basic question.
When I call 'onopen' for the first time in order to establish a connection, How can I know that server is down?
At this point when I call 'onopen' and pass a callback function - if server is down the method is stuck and doesn't return at all.
Thanks!

You can check this code , where I'm using EventBus.
Here is the Reference code
this.eventBus = new EventBus(this.URL);
this.eventBus.onopen = (e) => {
this._opened = true;
console.log("open connection");
this.callHandlers('open', e);
this.eventBus.publish("http://localhost:8082", "USER LOGIN INFO");
this.eventBus.registerHandler("http://localhost:8081/pushNotification", function (error, message) {
console.log(message.body);
//$("<div title='Basic dialog'>Test message</div>").dialog();
});
}
this.eventBus.onclose = (e) => {
this.callHandlers('close', e);
}
}

Related

how to reply and send message after receive message in node js using websocket

After receive message from client, I have to connect db(mysql) and save data and need to response the result to client and inform to other(admin) client.
So I need to get current socket client and special client(admin) from the socket list.
Is it possible to get current socket outside of wss connection block?
Thanks.
const WebSocketServer = require('ws');
// Creating a new websocket server
const wss = new WebSocketServer.Server({ port: 8080 });
const clients = new Map();
// Creating connection using websocket
wss.on("connection", ws => {
console.log("new client connected");
client_id = Date.now();
clients.set(client_id, ws);
// sending message
ws.on('message', function(message) {
//wss.broadcast(JSON.stringify(message));
console.log('Received: ' + message);
BuyCoin(message);
//console.log()
});
ws.on("close", () => {
console.log("the client has connected");
});
ws.onerror = function () {
console.log("Some Error occurred")
}
// ws.send('You successfully connected to the websocket.');
});
function BuyCoin(strValue){
const req_info = JSON.parse(strValue);
console.log(req_info.user_id)
console.log('betting!');
var sql = 'SELECT * from users where id = ? LIMIT 1'
connection.query(sql, req_info.user_id, (ws)=>{
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
}
}
You have several options:
#1: You can put the BuyCoin function logic inside the ws scope to make it a local function that is in scope of the ws variable for the current connection like this:
const WebSocketServer = require('ws');
// Creating a new websocket server
const wss = new WebSocketServer.Server({ port: 8080 });
const clients = new Map();
// Creating connection using websocket
wss.on("connection", ws => {
console.log("new client connected");
client_id = Date.now();
clients.set(client_id, ws);
// sending message
function BuyCoin(strValue) {
const req_info = JSON.parse(strValue);
console.log(req_info.user_id)
console.log('betting!');
var sql = 'SELECT * from users where id = ? LIMIT 1'
connection.query(sql, req_info.user_id, (ws) => {
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
}
ws.on('message', function(message) {
//wss.broadcast(JSON.stringify(message));
console.log('Received: ' + message);
BuyCoin(message);
//console.log()
});
ws.on("close", () => {
console.log("the client has connected");
});
ws.onerror = function() {
console.log("Some Error occurred")
}
// ws.send('You successfully connected to the websocket.');
});
#2: You can pass the ws value to your BuyCoin() function as an argument by just changing the function call from this:
BuyCoin(message);
to this:
BuyCoin(ws, message);
And, then changing your function declaration from this:
function BuyCoin(strValue) {...}
to this:
function BuyCoin(ws, strValue) {...}
Is it possible to get current socket outside of wss connection block?
No, there really is no such thing as the current socket. When using asynchronous code in nodejs, lots of different pieces of code can be "in-flight" at the same time so there is no global sense of the current socket. Instead, you have manage data specific to your current operation either by using scope, by passing as an argument or by setting as a properties on some other object that is passed as an argument. Since there is no natural object that BuyCoin() already has access to here that is specific to the user with the activity, then that leaves the first two options (using scope and passing as an argument).
FYI, this code looks a bit problematic because you're allowing the webSocket to send in the user_id that will be operated on without any visible authentication. That exposes you to rogue sockets that can pretend to be users that they aren't.
Also, it doesn't appear you have code that removes webSockets from the clients Map object when they disconnect so that Map object will just get larger and larger and contain lots of dead connections.
Another thing that needs fixing is that your connection.query() code is declaring a callback that does nothing but return another function and it tried to make up a value of ws that would never actually be passed. That function you create inside the callback is never called. Change from this:
connection.query(sql, req_info.user_id, (ws) => {
return function(err, rows, fields) {
//console.log("ix="+ix);
ws.send(rows[0]);
};
});
to this:
connection.query(sql, req_info.user_id, (err, rows, fields) => {
//console.log("ix="+ix);
ws.send(rows[0]);
});
And, combine that with one of the above two solutions to get access to the ws value.

Trigger a Client function with a service worker

I have a chat platform I'm building for fun. I have built notifications into the platform. On a browser it looks like this when you click the notification, with noticeSource being the user the new message is from. So it knows, to focus the page and then use the loadChat() function to load the chat associated with that user.
note.onclick=function(){
parent.focus();
console.log(this);
loadChat(noticeSource,el);
this.close()
};
However, I am also running this as PWA for android, so when it detects its on a phone it uses the Service worker showNotification method. I use this function to detect the click and to bring the app into focus.
self.addEventListener('notificationclick', function (event)
{
console.log("EVENT!",event.notification.data);
var target=event.notification.data;
const rootUrl = new URL('./index.php', location).href;
event.notification.close();
event.waitUntil(
clients.matchAll().then(matchedClients => {
for (let client of matchedClients){
console.log(client.url,rootUrl);
if (client.url.indexOf(rootUrl) >= 0){
console.log("Focus1");
return client.focus();
}
}
return clients.openWindow(rootUrl).then(
function (client) {
console.log("Focus2");
client.focus();
}
);
})
);
});
What I can't figure out is how to communicate between the SW and the client that the client should run the loadChat() function and pass along the user it should run it for. In general if someone could point me toward a resource that explains how to communicate between the SW and the client that would be appreciated. I've looked but haven't found anything and I am assuming it's because I'm not really clear on how service workers are suppose to work.
As is often the case, I found an answer after I posted the question. The client object has a method postMessage(), so once I have my client found I can use that to post a message with the userName, on the client side I can use eventListener navigator.serviceWorker.onmessage to catch messages from the sw and execute functions.
self.addEventListener('notificationclick', function (event)
{
console.log("EVENT!",event.notification.data);
var target=event.notification.data;
const rootUrl = new URL('./index.php', location).href;
event.notification.close();
console.log(clients);
event.waitUntil(
clients.matchAll().then(matchedClients => {
for (let client of matchedClients){
console.log(client.url,rootUrl);
if (client.url.indexOf(rootUrl) >= 0){
console.log(client);
client.focus();
client.postMessage(event.notification.data);
return ;
}
}
return clients.openWindow(rootUrl).then(
function (client) {
console.log("Focus2");
client.focus();
}
);
})
);
});
and on the client side
sw=navigator.serviceWorker;
sw.register('sw.js').then(function(registration){console.log("Scope:",registration.scope)});
sw.onmessage=function(event){
loadChat(event.data,document.getElementById(event.data));
}

WebSockets connection.send not function error

I have a Tornado client application which runs fine at its current state: In a simplified version, it has a structure like the folllowing code piece:
function comms(callback, newSession, connection) {
if (newSession == true) {
connection = new WebSocket('ws://localhost:9022/id/01234');
connection.onopen = function () {
alert("connected");
connection.send('hello world');
};
}
connection.onerror = function (error) {
alert('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
alert('>> message from Host: ' + e.data);
callback(e.data, connection);
}
}
I can connect, I can detect connection is on, I can send messages. I can receive messages. I can forward message via callback function and come back. No problem. All these are done via:
connection.onXXX event handler functions.
Now I want to send some unsolicited messages to server like the following:
function comms(callback, newSession, connection, request=false) {
if (newSession == true) {
connection = new WebSocket('ws://localhost:9022/id/01234');
connection.onopen = function () {
alert("connected");
connection.send('hello world');
};
}
connection.onerror = function (error) {
alert('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
alert('>> message from Host: ' + e.data);
callback(e.data, connection);
}
if (request == true) {
connection.send("request_msg");
}
}
Although connection is open, I can not send such a request message. I receive:
"connection.send is not a function" error.
As I understand, somehow send request must be wrapped into a function, like other connection.onXXXX event handlers. But I do not have any such event or handler.
How can I send my message?
It would seem you would need to do this within an event.
UPDATED:
The onmessage event is what is fired on the server side, so any client processing can't be done in that event handler. I would suggest the client side functionality should be handled in a different function (not comms).
According to this reference tutorial (an-introduction-to-websockets), just call the send request from within the function from the client that requests the message.
Ie. as per the tutorials example, found here, the request is called when the form is submitted / send message button is pressed. This is all wrapped in the onload function.
So you need some client side event or loop that can call the socket connection(socket).send() function, simply passing in text should be sufficient.
Does this help at all or does your application in it's 'complex' state achieve this already?

JavaScript callbacks function object

i try to learn node.js and try to create a new TCP Server connection. The code
var server = require('net').createServer(function(socket) {
console.log('new connection');
socket.setEncoding('utf8');
socket.write("Hello! You can start typing. Type 'quit' to exit.\n");
socket.on('data', function(data) {
console.log('got:', data.toString());
if (data.trim().toLowerCase() === 'quit') {
socket.write('Bye bye!');
return socket.end();
}
socket.write(data);
});
socket.on('end', function() {
console.log('Client connection ended');
});
}).listen(4001);
look at the callback function, after then, they call listen method. What is this for kind of object.
What it basically says is:
function myHandler(socket) {
// everything up to socket.on('end')
}
var server = require('net').createServer(myHandler);
server.listen(4001);
So it's just creating a socket server with a handler function, and then make the server listen to port 4001.

How to determine server disconnection from SignalR client?

How can a SignalR JavaScript client detect when a connection with the server is lost?
A hub has a method disconnect which will allow you to add a callback when disconnection takes place:
myHub.disconnect(function() {
alert('Server has disconnected');
});
If you aren't using hubs then the code for the disconnect method will help you out:
$(connection).bind("onDisconnect", function (e, data) {
callback.call(connection);
});
This shows the syntax for hooking onto the onDisconnect event of the underlying connection.
If you are using hubs then implement the IDisconnect interface.
public class ChatHub : Hub, IDisconnect
{
public void Disconnect()
{
Debug.WriteLine(Context.ConnectionId + " disconnected");
}
}
On persistent connections you can override OnDisconnectAsync,
(from the SignalR wiki at https://github.com/SignalR/SignalR/wiki/PersistentConnection )
public class MyEndPoint : PersistentConnection
{
protected override Task OnDisconnectAsync(string clientId)
{
return Connection.Broadcast("Client " + clientId + " disconncted");
}
}
This worked for me using "#aspnet/signalr": "^1.0.0" npm package
const connection = new signalr.HubConnectionBuilder()
.withUrl('url')
.configureLogging(signalr.LogLevel.Information)
.build()
connection.onclose(() => {
// close logic goes here
})
The SignalR 2.0 way of doing this is like so:
$.connection.hub.disconnected(function () {
console.log('Connection disconnected')
});
http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-javascript-client#connectionlifetime
Starting with SignalR v0.5.1 it works this way:
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.reconnecting) {
console.log("liveFeed is reconnecting!");
}
else if (change.newState === $.signalR.connectionState.connected) {
console.log("liveFeed is connected!");
}
});
For more details check this website:
http://weblogs.asp.net/davidfowler/archive/2012/06/10/signalr-0-5-1-released.aspx
The below, worked for me:
var connection = $.hubConnection('signalrConnectionUrl');
connection.disconnected(function() {
console.log('Connection disconnected');
});
I'm using version: 2.1.2
See the following link for reference: Link
The provided answers will no longer work.
This is the new way to stop/disconnect connections.
myHub.stop().then(() => {
alert('Server has disconnected');
});

Categories