getServerTime and syncing game client clocks

liortal53
liortal53
edited August 2013 in Native
Hi,

I'm looking for a way to implement an algorithm to sync all game clients with a single time source, such that their clocks will be in sync.

The Photon SDK (NDK for Android) provides the getServerTime() function to retrieve the server's time.

Is this value being updated once or multiple times (kept in sync) ?
If it's synced, does this value compensate for the RTT ? (the value returned by this function already adds RTT/2) ?

The documentation for this function doesn't specify anything.

I'd love to get some advice (if you have any) on how to perform this sync.

*Our game clients use mostly UDP, varying between reliable and unreliable delivery.

Thanks!
Lior

Comments

  • Hi Lior.

    It's synched once on connect and you can trigger resyncs by calls to fetchServerTimestamp(). Resyncs only make sense, if the latency improves significantly.

    "If it's synced, does this value compensate for the RTT ? (the value returned by this function already adds RTT/2) ?"
    Yes, that's already done.

    The current implementation of getServerTime() looks like this:
    [code2=cpp]return serverTimeOffsetIsAvailable?serverTimeOffset+GETTIMEMS():0;[/code2]
    with GETTIMEMS() being a macro that on Unixes (which includes Android) is defined to a function, that retrieves the current local time from gettimeofday() and returns it as a millisecond value.
  • Thanks for the quick reply.

    So if i understand correctly, this function will return on every call, the server time by using the offset between local and server (as determined on connect) + current time (thus making it up to date on every call, unless drastic changes to latency occur) ?
  • Yes, that's correct.

    However when using our LoadBalancing API, which supports multiple servers, there is one catch:
    Whenever you create/join or leave a game room in LoadBalancing, the client will switch between master and game server under the hood. That includes a refetch of the server time to get in sync with the new server. So you should not compare a timestamp that you have received by a call to getServerTime() outside of a room with one inside of a room and its also not safe to compare a timestamp, that has been determined in room a, with one, that has been determined in room b, as they might get hosted on different game servers.
  • Got it. Thanks.
  • While testing this now, i am getting a negative value when calling getServerTime(): -1467223907

    (This is a result when running on an Android device).

    Why is that? (can that be an overflow issue since the returned type is int, and not long ?)
  • 1. It doesn't really matter if the returned type is an int or a long, as on a 32bit architecture both are 32bit, same as both are 32bit on a 64bit architecture, when compiling with a llp64 compiler (msvc). They only differ for legacy 16bit architectures, where int is only 16bit, and for 64bit architectures with lp64 compilers (gcc and clang), where long is 64bit. As Android currently only is available as 32bit, int and long always have the same size on Android. If you want a 64bit datatype, then you should not use long, but long long, which is 64bit on 32bit and 64bit architectures, no matter if the compiler uses lp64 or llp64 for 64bit. Photons int64 datatype also is just a typedef for long long.
    In general its a good idea to avoid long altogether and only use char, short, int and long long, as those will always be 8, 16, 32 and 64bit on all architectures, that have some meaning in nowadays, while long will be 32bit on some, but 64 bit on some other platforms.

    2. Yes, the values returned by getServerTime() will overflow every 49 days. Photon games that need to compare timestamps which differ by more than 24 hours are just a too rare edge case, so that it doesn't make sense to let all other games waste 4 more bytes for a 64bit time, which they don't actually need.
    You may also want to have a look at the class Common::EGTime, which offers an interface for doing overflow-secure timestamp comparisons (additions and substractions are always overflow-secure with signed integer types (e.g. 10 - -5 == 15) )