Socket.io countdown synchronously?

4.1k views Asked by At

On my server I call two emits at the same time, which looks like this.

if (songs.length > 0) {
    socket.emit('data loaded', songs);
    socket.broadcast.to(opponent).emit('data loaded', songs);
}

The one is for opponent and the other for himself.

Once the data is loaded a countdown should appear for both players on my android app. For me it is important that they see the same number at the same time on their screen. To be precise it should run synchronized. How can I do this?

4

There are 4 answers

0
SUNDARRAJAN K On BEST ANSWER

As far as js timers are concerned the will be a small amount of difference. We can reduce the difference in time with reduce of latency time, with the difference between the request and response time from the server.

function syncTime() {
console.log("syncing time")
var currentTime = (new Date).getTime();

res.open('HEAD', document.location, false);
res.onreadystatechange = function()
{
    var latency = (new Date).getTime() - currentTime;
    var timestring = res.getResponseHeader("DATE");
    systemtime = new Date(timestring);
    systemtime.setMilliseconds(systemtime.getMilliseconds() + (latency / 2))
};
res.send(null);
}

Elapsed time between sending the request and getting back the response need to be calculated, divide that value by 2. That gives you a rough value of latency. If you add that to the time value from the server, you'll be closer to the true server time (The difference will be in microseconds)

Reference: http://ejohn.org/blog/accuracy-of-javascript-time/

Hope this helps.

0
Giorgio Cerruti On

I have made an application and I had the same problem. In That case I solved the problem leaving the time control to the server. The server send to the client and the client increases the time. Maybe in your case you could have problem with connection. If the problem exists you can leave clients to increase time by yourself and some times send a tick with correct time for sync.

0
Avoid On

Add time into emit message. Let's say that songs is an object with
{"time" : timeString, "songs" : songsList}.

If we consider devices time is correct You can calculate the time needed for information to travel and then just use server timer as a main calculator.

The client would get the time when countdown should start:

var start = false;
var startTime = 0;
var myTime = new Date().getMilliseconds();
var delay = 1000 - myTime;

setTimeout(function(){
    intervalID = setInterval(function(){
        myTime = new Date().getTime();
        //console.log(myTime); to check if there is round number of milliseconds
        if (startTime <= myTime && start = true) {startCountdown();}
    }, 100); //put 1000 to check every second if second is round 
             //or put 100 or 200 is second is not round
}, delay);

socket.on('data loaded', data){        
    startTime = data.time;
    start = true;
}

function startCountdown(){
    //your time countdown
}

And that works fine when 2 clients are from same time region, therefore You will need "time converter" to check if time is good due to time difference if You strictly need same numbers.

After the countdown has ended You should clearInterval(intervalID);

0
Heartbit On

I could give you something like bellow but I am not tested. This solution have these steps:

  1. Synchronize timers for client and server. all users have the same difference with server timer.
  2. For the desired response/request get clients time and find the differences with server time.
  3. Consider the smallest as first countdown which will be started.
  4. For each response(socket) subtract the difference from smallest and let the client counter starts after waiting as much as this time.

The client that gets 0 in response data will start immediately. and the main problem that you may will have is broadcast method which you can't use if you think this solution will be helpful. This is a post may will help you.