Author Topic: Time synchronisation and manual ping  (Read 5771 times)

grofie

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 17
    • View Profile
Time synchronisation and manual ping
« on: November 27, 2013, 09:57:27 AM »
Hi guys,

I could not find the direct answer to my problem, so I just gonna ask again here:

I understand synchronizing the time over network does not come out of the box in TNet (which is quite sad since it seems to be requested quite often (to give a broad hint ;))).

To get this done manually I followed the way described in several post before:

Quote
If you really want to sync game time, do it on the host (TNManager.isHosting check), and send (Time.time + TNManager.ping). On the clients, add TNManager.ping to it as well. Record the difference between the value and your own Time.time, and use this offset in the future.

But the time still differs on two local instances.

Afterwards I tried to synchronize by sending the server time several times and taking the median value to filter spikes.

Still the time differs on both instances.

What I don't understand is

  • Why the ping is always the same in every RFC? I sending the time sync RFC every half second, but the ping is always the same. When I restart the game I got a different ping value
  • How can I manually start a ping request? I tried TNManager.BeginSend(Packet.RequestPing); TNManager.EndSend(); but this just let the ping grow with every call (i.e. 253, 435, 451 ...). The difference between the last steps look more like the actual ping to me, so what am I doing wrong?
  • How come the ping is so high (150 - 300) between two instances running on the same machine? My guess its because number (1.), the initial ping is damn high but never gets updated!?
  • How come the server has the same high ping to himself?

Thanks allot in advance.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Time synchronisation and manual ping
« Reply #1 on: November 27, 2013, 10:28:56 AM »
Network time will always differ. It's never going to match perfectly. The time it takes each packet to travel to its destination is never constant, and can vary quite a bit.

Manmax75 posted a Network Time implementation here:
http://www.tasharen.com/forum/index.php?topic=5788.msg30798#msg30798

Ping should not be sync'd manually. It's something that's done for you every so often. Running two instances on the same machine you should be seeing a pretty low ping (assuming 60 fps it should be exactly 16-17 ms -- and that's only because TNet packets get retrieved in Update()). If you're running over wifi however... there are other factors. I once had a router that had both 2.4 Ghz and 5 Ghz bands (dual band router). When going from 2.4 Ghz to 5 Ghz, and vice versa, the ping was obscene -- something like 600 ms+. 2.4 to 2.4 and 5 to 5 was instant.

grofie

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 17
    • View Profile
Re: Time synchronisation and manual ping
« Reply #2 on: November 27, 2013, 11:58:23 AM »
Thanks for your fast reply.

I am running two unity instances (two editor or even two windows builds) on one machine and get these high pings, so no rooter or anything is involved. Even if the server pings itself, the ping is high like that.

When is the ping updated? Like I said, sending RFC from the server does not refresh the ping, I am always getting back the same value.

Thanks again for pointing me to the network time script from Manmax75, I gonna try that one out.

Manmax75

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 3
  • Posts: 32
    • View Profile
Re: Time synchronisation and manual ping
« Reply #3 on: November 27, 2013, 06:06:48 PM »
Do you know how long the main thread is taking? (Check profiler if you can)
If you have a lot going on, or are processing a lot of data (like iteration through massive lists or something) then you increase the ping because the server/client takes longer to respond.

Ping=[Client Process Packet->Client Send Packet----TRANSIT----Server Receive Packet->Server Process Packet->Server Send Response->----TRANSIT----Client Receive Packet->Client Process Packet]

Also bare in mind with my implementation of time synchronization you will NEVER get perfectly accurate time. The accuracy is however ~10-80ms from my tests, which is perfectly acceptable for online gaming. You can improve this by increasing the amount of requests to send to build the average list, it should be commented in the file what you need to change to improve accuracy.

Even then though, it's unlikely you'll ever get below ~10ms of accuracy.

grofie

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 17
    • View Profile
Re: Time synchronisation and manual ping
« Reply #4 on: November 28, 2013, 03:34:15 AM »
Thanks Manmax for your answer, but it missed my point a bit:

A few milliseconds of inaccuracy wouldn't be bad. But now I got inaccuracy for half a second, which is quite obviously on the start of a racing game. Like I mentioned, the problem is the ping which always stays high on the same level. When I got pings like 250ms, but the actual ping on two local instances should actually be around 16, that's not a surprise. The ping is calculated on level start, so it is quite high because of the level loading process. But I still don't get why the ping is not getting updated afterwards.

The game didn't go far yet (no big data processing), my computer here at work is amazingly fast, so the profiler data is inconspicuous.


//supplement

While writing this post I got an idea myself:

My initial approach was like this (like the quote in the first post): On level start the server sent his time to the other player every half second while the countdown went down. The client tried to calculate the offset between his time and server time with the added ping. Since the ping did not get updated, the offset differed around two times the ping.

Now I let the client send (empty) RFC calls to the server in similar intervals. By that at least the ping on the server side gets updated and now shows the expected 16-17ms. The ping on client side still stays wrong on high level and does not get updated. To avoid this problem I simply add the ping twice on server side now. Now the time is the equal (enough) on both instances.

I am not totally happy with this solution, because it feels a bit like a hack (sending empty RFCs, using only the server ping) and not like the solid way to do this, but at least it is working. I am going to test it with higher latency now.

Any hints or opinions are still welcome.  ;D

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Time synchronisation and manual ping
« Reply #5 on: November 28, 2013, 04:06:36 PM »
TNet requests ping updates every 4 seconds:
  1.                 // Request pings every so often, letting the server know we're still here.
  2.                 if (mTcp.isConnected && mCanPing && mPingTime + 4000 < mTime)
  3.                 {
  4.                         mCanPing = false;
  5.                         mPingTime = mTime;
  6.                         BeginSend(Packet.RequestPing);
  7.                         EndSend();
  8.                 }
You can find this code in TNGameClient.ProcessPackets. This is why you don't need to request them yourself. In fact, in doing so yourself you're breaking some of its logic where it records the time of the packet being sent. Just have a look at the code, and don't try to send pings yourself.

grofie

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 17
    • View Profile
Re: Time synchronisation and manual ping
« Reply #6 on: December 02, 2013, 05:49:45 AM »
Hi Aren,

thx for your answer. Four seconds is quite long, since my initial countdown is only three seconds long. The first ping is super high, probably because of level loading. At least the ping is updating on server side when the client sends a RFC.

Still would be nice if the ping could be forced manually. I could write a setter of the ping interval, but I do not want to hack into the TNet code..