Environment
Server: Node.js
Client: Browser
Communication: Socket.io
I already handle on server side when a client disconnects. But I wonder, is it possible to handle a server disconnection on client side?
Said in other words,
suppose server enters exception state and shuts down, how can the client know this happened? Can I use the very same code
socket.on('disconnect', function() {...});
on client?
Appreciate the help.
Things tried
To check if client is getting notified via
socket.on('disconnect', function() {...});
I throw the following exception in the server:
setTimeout(function () {
console.log('Throwing error now.');
throw new Error('User generated fault.');
}, 9000);
In client I have:
socket.on('disconnect',function(data){ console.log('Server disconnected you'); } );
But the log message in client never happens. ¿?
From the socket.io client docs:
Events
connect. Fired upon connecting.
disconnect. Fired upon a disconnection.
So yes, the client works in identical manner to the server.
Checkout other socket.io client-side events. https://github.com/Automattic/socket.io/wiki/exposed-events
Try to listen 'reconnect_failed' or 'error' instead of 'disconnect'.
Related
I'm using WebSocket & nodeJs. I can detect user's connection and present it, but I can't detect user's disconnetion. The method on('close',function()....) happens when I shut down the server and not when a user closes the tab or something. What can I do? I realy don't know how to do it right now. Thank you all! Hoping you'll help me.
To detect socket disconnection, I use this method which works fine :
socket.once('disconnect', function () {
// socket is disconnected
});
Or
socket.on('disconnect', function () {
// socket is disconnected
});
Hope it helps.
You should implement heartbeat requests (inside websocket connection) from client to server (every 20-30 sec) and limit connection to some period (40-50 sec) - this can be done in web server (or even load balancer settings).
When server find that there is no heartbeat request it means that this connection is broken - client closed tab or something.
Updated: oh! Seems socket.io have heartbeat implementation, so my answer was a bit common.
io.sockets.on('connection',function(socket){
socket.on('disconnect', function(){
// Your stuff here
});
});
I'm developing a React Native application and I want to use the WebSocket class to communicate with my Socket.io server.
I can connect to the server just fine, but I'm having problems sending messages to it using the .send() method.
I tried this on React Native:
var socket = new WebSocket("ws://host:port/socket.io/?transport=websocket");
socket.onopen = () => {
console.log("connected");
socket.send('data');
};
On my Socket.io server I have this listener that I created just for testing:
socket.on('data', function(data) {
console.log("data");
})
The connection does work, and I'm able to see that on the server too. But when I do socket.send('data') the disconnect event gets called on the server rather than the data event I wrote above. (I tested this by using a function to call the .send() method, so this does cause a disconnect on the server)
Can anyone shine some light on this?
That's because Socket.io is not exactly compatible with WebSocket - there are initial handshakes, connection fallbacks (eg. when no WS is available, use AJAX long pooling or other technique) and other things that Socket.io hides from you to make your life easier. Essentially, Socket.io should be seen as a separate protocol.
To connect to a Socket.io server, you have to use Socket.io client library.
ws.send(`42${ JSON.stringify(["message", { command: "register" }] }`), err => {
if (err) console.log("err", err);
});
This code using the ws pacakge as the example.
You need to add the 42 to tell socoket.io server that you are sending message, the {command: "register"} is the data you send, the "message" is the channel that socket.io is listening on.
io.on("message", (data) => {
console.log(data); // => {command: "register"}
});
Explain: this is the engine.io-protocol that socket.io is using. Check it's spec.
The best solution is using socket.io on both side or don't use socket.io at all.
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.
I have a socket.io server/client. When a client safely disconnects, on the server side, the line
socket.on('disconnect', function() {
});
is called.
However, if the client server crashes, then socket.on('disconnect') is never called; I know this because I recursively print out wss.sockets.connected.length and the number does not decrease.
How can I check that such a crash has happened on the server?
You should eventually receive the disconnect event, because socket.io has a heartbeat mechanism. I don't think there is any other way to detect a client crash. It does take some time though.
Heartbeat has been explained well here:
Advantage/disadvantage of using socketio heartbeats
When server calls disconnect(), the reason given to disconnect handler is: io server disconnect. And when server stops, the reason is: transport close.
So you can check this by adding a condition:
socket.on('disconnect', function(reason) {
if (reason === 'transport close'){
console.log('Server Crashed');
}
});
im using this simple code
Client.html
http://pastebin.com/c1C2F9MQ
Server.js
http://pastebin.com/Cqjhjfwm
Everything working fine till the last step of my client code
socket.on('add', function(data) {
socket.broadcast.emit('AAA');
});
It seems that the socket add never comes but on my server I have
socket.on('Text', function(data) {
socket.emit('add', data);
});
And I tested if socket text was coming and it does, I cant find the problem
Thanks
socket.broadcast.emit sends message to all sockets connected to server except the concerned socket. So most likely add does come to server but it broadcasts AAA which your client cannot get. Use io.sockets.emit to send to all connected sockets. Change this
socket.broadcast.emit('AAA');
to
io.sockets.emit('AAA');
Update
I too overlooked that you are calling socket.broadcast.emit from client not from server. It would have shown error on browser console, since broadcast is absent on client.
Currently your on('add') code on the client side is within the on('connect') event which is not correct...
You need to take it ouside there, so it becomes:
socket.on('connect', function () {
$('#button').click(function() {
var addtext = $('#text').val();
socket.emit('Text', addtext);
});
});
socket.on('add', function(data) {
socket.emit('AAA');
});
EDIT: I also just noticed you had socket.broadcast.emit() in your client side code. As far as I know there's no concept of broadcasting from the client. If you want to broadcast something then the client should send it to the server then the server broadcasts to the other clients.