Socket.io countdown synchronously? [duplicate]
Asked Answered
Q

4

8

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?

Quality answered 25/12, 2016 at 10:52 Comment(4)
perhaps have the client send a token back, signifying where they are on the countdown, and only send a message to count down when they have the same value? I think it might be the only way, unfortunately, if you take in to account the latency of each user.Carbineer
@SamJudge can you explain more with code examples?Quality
How precise do you need to be? How far apart are users from one another, and what's the latency between users and server? With your code above, both users should be pretty close to being in sync, but that's really depends on your definition of "in sync"...Buchholz
sync clients clocks to server, send a future timestamp with response, allowing a few MS for lag. when the time is reached on the client, fire the event. both players should have the payload by then (msLag *2)Gi
P
1

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.

Praline answered 3/1, 2017 at 9:54 Comment(0)
P
0

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.

Prerequisite answered 29/12, 2016 at 16:28 Comment(0)
B
0

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.

Bronnie answered 1/1, 2017 at 10:41 Comment(0)
V
0

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);

Vernievernier answered 2/1, 2017 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.