I have server and clients in node.js.
Every time client connects to server:
var response = {};
if (currentPlayers < maxPlayers) {
currentPlayers++;
response.username = currentPlayers;
players[currentPlayers] = {
score: 0
};
socket.join('players');
} else {
if (currentPlayers === maxPlayers) {
//Set a little delay
setTimeout(function () {
//I also tried this:
//players_sockets.forEach(function (s) {
// s.emit('start');
//});
io.to('players').emit('start');
}, 1500);
}
}
Server checks is there enough players for game, if it is, server emits start
message. The problem is that some clients doesn't receive this message(to be current: mobile devices(e.g. meizu mx5, iphone 5, iphone 5s and some others).
I watched debug: they are using long-polling.
Desktop clients, which are connected with WebSocket are okay.
How i need to fix this? Or maybe I'm doing something wrong?
The iPhones don't need long polling according to this...
http://caniuse.com/#feat=websockets
There's some mention of it crashing through a proxy so if there's that issue maybe try not to to confirm?
Meizu. ? No clues. Hopefully not a large market share. Maybe ask them to support websockets well.
@MasterJames maybe I'm not right about long polling. This is log from iphone5s(ios8.1) safari (i got this from remote debugging)
Navigated to http://192.168.1.2/play.html
socket.io-client:url parse http://192.168.1.2 +0ms
socket.io-client new io instance for http://192.168.1.2 +9ms
socket.io-client:manager readyState closed +10ms
socket.io-client:manager opening http://192.168.1.2 +1ms
engine.io-client:socket creating transport "polling" +0ms
engine.io-client:polling polling +2ms
engine.io-client:polling-xhr xhr poll +1ms
engine.io-client:polling-xhr xhr open GET: http://192.168.1.2/socket.io/?EIO=3&transport=polling&t=LI_-qTS +2ms
engine.io-client:polling-xhr xhr data null +1ms
engine.io-client:socket setting transport polling +2ms
socket.io-client:manager connect attempt will timeout after 20000 +11ms
socket.io-client:manager readyState opening +1ms
engine.io-client:polling polling got data ArrayBuffer +68ms
engine.io-client:socket socket receive: type "open", data "{"sid":"RYFHh8VhCPAgN7R3AAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}" +26ms
engine.io-client:socket socket open +2ms
socket.io-client:manager open +95ms
socket.io-client:manager cleanup +1ms
socket.io-client:socket transport is open - connecting +1ms
engine.io-client:socket starting upgrade probes +4ms
engine.io-client:socket probing transport "websocket" +1ms
engine.io-client:socket creating transport "websocket" +0ms
engine.io-client:polling polling +3ms
engine.io-client:polling-xhr xhr poll +1ms
engine.io-client:polling-xhr xhr open GET: http://192.168.1.2/socket.io/?EIO=3&transport=polling&t=LI_-qVA&sid=RYFHh8VhCPAgN7R3AAAB +2ms
engine.io-client:polling-xhr xhr data null +0ms
engine.io-client:polling polling got data ArrayBuffer +59ms
engine.io-client:socket socket receive: type "message", data "0" +1ms
socket.io-parser decoded 0 as {"type":0,"nsp":"/"} +69ms
engine.io-client:polling polling +3ms
engine.io-client:polling-xhr xhr poll +1ms
engine.io-client:polling-xhr xhr open GET: http://192.168.1.2/socket.io/?EIO=3&transport=polling&t=LI_-qWB&sid=RYFHh8VhCPAgN7R3AAAB +0ms
engine.io-client:polling-xhr xhr data null +1ms
socket.io-client:manager writing packet {"type":2,"data":["register",null],"options":{"compress":true},"nsp":"/"} +10ms
socket.io-parser encoding packet {"type":2,"data":["register",null],"options":{"compress":true},"nsp":"/"} +1ms
socket.io-parser encoded {"type":2,"data":["register",null],"options":{"compress":true},"nsp":"/"} as 2["register",null] +4ms
engine.io-client:socket flushing 1 packets in socket +12ms
engine.io-client:polling-xhr xhr open POST: http://192.168.1.2/socket.io/?EIO=3&transport=polling&t=LI_-qWR&sid=RYFHh8VhCPAgN7R3AAAB +3ms
engine.io-client:polling-xhr xhr data 19:42["register",null] +2ms
engine.io-client:socket probe transport "websocket" failed because of error: transport closed +9ms
engine.io-client:polling polling got data ArrayBuffer +26ms
engine.io-client:socket socket receive: type "message", data "2["registered",{"username":1}]" +2ms
socket.io-parser decoded 2["registered",{"username":1}] as {"type":2,"nsp":"/","data":["registered",{"username":1}]} +44ms
socket.io-client:socket emitting event ["registered",{"username":1}] +1ms
@MasterJames It receives message "register", but after that server emits "start" event and iphone doesn't receive it.
I'm no expert here just learning but isn't the point of websockets to replace long polling?
Socket.io doesn't replace long polling. And by design it can fallback to XHR long polling if web sockets are unavailable or socket.io isn't too warm and fuzzy about the web socket implementation. For whatever reason some browsers/clients make it switch to the fallback. I worked on an application where I only wanted web sockets. So I enforced it via the connection configuration using `"transports" : ["websocket"]`` and used Modenizr to ensure web sockets were available. This did the trick for me and the browsers quit performing a fallback to XHR long polling.
long polling or not, should not be a reason for not receiving a message.
the code seems to require that one more player than allowed connected for the start message to be emitted.
check that you still have all players in room. Do some console logs or other debug to check that connections remain.
@davidrinnan Do you mean this:
player1 connected
player2 connected
player1 closed connection
'start' event emitted
?
I don't know. I'm just saying it looks like the io.to('players').emit('start'); only run in the else clause. Which evaluates if there are more players than allowed. But without seeing all the code it is hard to say, don't know the base values of your constants etc.
But anyways there shouldn't be a difference in how your clients work in terms of messages if they are using web sockets or xhr. At least that is not my experience.
basically the last client connecting starts the game but doesn't join it...
@davidrinnan my logic is: if there enough players(currentPlayers === maxPlayers) -> then we tell to all players that we need to start the game. Unfortunately the first players don't receive 'start' message.
I forgot to update my code, here the new one, but the problem is still occurs:
if (currentPlayers < maxPlayers) {
currentPlayers++;
response.username = currentPlayers;
players[currentPlayers] = {
score: 0
};
socket.join('players');
} else {
response.username = false;
}
//Check if we have enough players and we can start a game
if (currentPlayers === maxPlayers) {
setTimeout(function () {
io.to('players').emit('start');
log.success("Game started!");
}, 1500);
} else {
log.error("Not enough players");
}
is it only the last player that get the message, or more sporadic?
@davidrinnan it's random. I test with 3 players: sometimes only first don't receive, sometimes second and first players.
check network console dev tools in chrome on the clients
you should see some xhr. And then a continuous web socket.
could it be an issue with retry not working. and that you restart (or don't) the web server but forget to reload clients etc?
@baconface now i get #2557
Enable only websocket
helps. this comment
But I will try to find why with XHR it fails.
Most helpful comment
Socket.io doesn't replace long polling. And by design it can fallback to XHR long polling if web sockets are unavailable or socket.io isn't too warm and fuzzy about the web socket implementation. For whatever reason some browsers/clients make it switch to the fallback. I worked on an application where I only wanted web sockets. So I enforced it via the connection configuration using `"transports" : ["websocket"]`` and used Modenizr to ensure web sockets were available. This did the trick for me and the browsers quit performing a fallback to XHR long polling.