I am making a game where a node server speaks to javascript clients using socket.io. Players can connect and disconnect from the game and the server keeps track of who is connected. However, I have found that on many occasions when i close the server, close all open client tabs, then restart a new node server, the number of clients connected seems incorrect.
For example, I will connect with just one client but the node debugger shows that the server is keeping track of three sockets.
This is a problem because often these orphaned clients will receive messages from the server or timeout, and this messes up the game logic on the server (it was not expecting this many players etc.)
I think the reason this is happening is:
1. Clients in socket.io automatically attempt a reconnect periodically when they are disconnected
2. When closing a tab the sockets associated with that page are not being "flushed" or cleared for some reason.
3. When the server is closed and then started up again, these unflushed clients think "oh, the server is back up, i will try and reconnect"
How can I tell the difference between sockets that have had their tabs closed/were associated with the old server, and new clients attempting to connect to the newly restarted server? Or is there a way for me to ensure the clients get "flushed" when either the server is closed or a tab?
Without any code, I am really only guessing here.
http://socket.io/docs/#sending-and-receiving-events
Above, you will find code and I will copy it. Basically, you need to listen to the 'disconnect' event on the socket and remove your reference of the client from whatever array you are using to keep track of your clients.
socket.on('disconnect', function () {
// remove from list here
});
Connections from the browser will die on tab close and this event will be called when this happens. Yes, if you reopen the page, they will reconnect.
You should create some sort of "handshake" that actually adds a client to your list of game clients. Anyone can technically connect to a websocket. It can be as simple as emitting an "init" message that is empty but at least have something there.
Related
This question already has answers here:
Sharing websocket across browser tabs?
(9 answers)
Closed 11 months ago.
Some people already have asked this questions in some other places, Im just not sure if it exists here. Anyways, Im using Primus.io with engine.io as it's transformer. Im wondering if it's possible to have shared websocket connection on the browser(client). Like if I connected one client and connect another one on the other tab. Ideally they should get same connection that if I send something through the socket both tabs should be able to get the message.
Other's have mentioned about using the localStorage as a way to share/communicate the same data across different tabs, But I just don't find it neat.
Your help is greatly appreciated.
Best,
Each tab will have a separate connection to the server and has a unique socket id.
If you want to emit a message to every socket for a user id or session id you need to have something to map a user or session to its multiple socket connections.
In Socket.IO, they have a concept of a "room".
On connection you can add the socket to a room. This example uses a passport.js authed username for the grouping.
io.on('connection', function(socket){
socket.join(socket.request.user.username);
});
Then you can send a message to all sockets for that room.
io.to(username).emit('some event'):
Socket.IO cleans up the room on disconnect for you.
https://github.com/cayasso/engine.io-rooms is an implementation of rooms for engine.io that might be useful.
In simple terms
On connection, you want to add the new socket to a list of sockets for a user.
On disconnect, you want to delete the socket from the list of sockets for a user.
On emit, you want to emit a message to all sockets in the list for a user.
If the code in your two tabs cooperate, it is possible to share data from webSocket connection in one tab with the other tab. When a tab opens, it would have to find out if any other tab was already open with an existing webSocket connection and it would have to then ask that tab to share its data with the new tab. This is not a trivial operation as browser windows don't have an easy way to find out about other browser windows unless the new window was opened by the prior window's script, not opened by the user.
But, if each of your windows just attempts to make a webSocket connection to the server, they will each get their own webSocket connection. There is no automatic sharing of webSocket connections between tabs.
FYI, the usual behavior here is that each window just gets its own webSocket connection to the server and then the server just separately communicates with each browser window. If some information from one window needs to be kept in sync with the other window, then you can code your server to keep both up-to-date in that way.
I am trying to get a handle on the various connection/disconnection events and how to use these to make sure that my application will always terminate gracefully.
I understand that socket.io will automatically attempt to reconnect a specified number of times. It is my understanding that as the connection goes down and subsequently reconnects there will be a disconnection event fired server side. I do not care about the connection temporarily going down so long as it comes back up at some point.
However if there is a more permanent disconnect, I do care about this and would need to update data such as connected users. I understand that on the client side you can get a reconnect_failed error object but I do not believe you can listen for this on the server. Is there any way to get notification on the server side that the connection is down and reconnection has failed? If so how does socket.io implement this?
I could issue a timeout upon a disconnection event server side that removes users if there is no reconnection. I could also have the server ping all connected clients at certain intervals. Are these kinds of solutions the only way to completely deal with all kinds of possible disconnections?
Here's the scenario, I have a client side application, served by PHP on a different server to the node.js + socket.io application. It can connect and receive broadcasts sent from the server. If the connection drops, the application falls back to polling a database (using setInterval()). It attempts to reconnect every 5 polls, and it can successfully reconnect and continue to receive messages.
My problem occurs when the user loads the page and the node server cannot be reached (I turned it off for testing), I then turn on the server and on the 5th poll, it successfully connects to the server, using socket.socket.reconnect();. However, whenever the server broadcasts messages, it doesn't fire the event. Note that this doesn't happen when testing on a phone (which falls back to a different socket method)
I have already seen the question found here Reconnection in socket.io problem in `socket.on('message',function(){})`, however, the socket has not previously been connected so I don't think it could be the session?
EDIT: I changed the socket.socket.reconnect() to socket.socket.connect() and it fixed the problem. If someone could explain the reasons of why this works I'd like to know. I know its because the server isn't actually reconnecting, but would like more info.
Thanks.
well you possibly know the reason for this. server is not reconnecting. it is actually connecting. when you tell socket.io to reconnect it searches for the previous connection handle and thats where the problem arises.
I just got started in node.js and created a server where browser clients can connect to it.
Problem: When there is an error in the nodejs server and it crashes and restarts, the connected clients will usually reconnect automatically, but I notice that many clients usually make multiple reconnections back to the server!
How can I prevent that from happening, either serverside or clientside?
I suggest implementing it server-side. Apperantly, there is no implementation of it in socket.io (Source Code), so you can use key-value caches like Redis and map every connection in the Redis and check if user is already connected.
I am working with socket.io and node.js. I'm am having problems tracking which users are online because of the few seconds delay before socket IO recognises an XHR-Polling client has disconnected.
If an XHR-Polling client refreshes the page their new connection message seems to precede their disconnection message. This causes confusion when trying to track which users are online.
One solution could be to detect the transport method on the serverside and delay the connection for XHR-Polling clients to ensure that the disconnection functions have been run first.
Has anyone had any experience of this?
The main problem with presence, as #davin and #jcolebrand point out in the comments, is that connections alone can't be relied upon. Network devices can hold on to connections after a user has navigated away from a page. So, you need something else in place to confirm a users presence.
This is something we've added support for in Pusher and we do this using something called Presence Channels.
We manage this using a unique user id, which you (the developer) have to supply when a user connects, in combination with a unique socket id which identifies the connection. Since this unique user id can only occur once within a presence member list it means that that user will only be listed once - even if they have multiple connections open, and thus multiple socket connections.
The same idea can be applied to HTTP connections.
The general approach for this is to use the session to uniquely identify the user. In that way even if they are just a "Guest" you can still identify them as long as they are allowing the use of cookies.
So, the number of users on your system should only ever max at the number of active sessions you have running on your server.
Hope this helps. Let me know if you'd like anything clarified.
I'm developping a chat support solution and the attendent have to know when a client connect. With websocket works fine, but with whr-pooling, sometimes the attendent just disconnect (with 5 seconds in some cases). Sometimes dont heppend. What I do: I just enter the page and wait looking the terminal app.
I'm using nodejs, nowjs
What version of socket.io are you using? I encountered this issue and solved it on this post. It turns out there was a bug introduced in socket.io 0.9.5 on the request sent when the beforeunload event was triggered that prevented the proper disconnection.