🏗️ ΘρϵηΠατπ🚧 (under construction)

Clock Delta Problem
Suppose you have two computers on different networks with the following assumptions
  • Each computer has a system time which may be different from the other, but this offset is constant. Let tc,tc be the client and server time, then there exists some Δc such that tc+Δcts
  • Each computer clock advances forward at the same rate
  • The travel time from the client to server denoted by cs and sc respectively, and there exists some Δt such that cs+Δtsc
In the clock delta problem, you do not know the value of Δt nor Δc, and you must design a program which estimates these values. The program may send packets over the network with any required information.

The reason for Δt is that the travel time from client to server is always the same and the travel time from the server to client is always the same, but the two times my differ (different packet routing).

Time Conversion Function
Suppose that tc,ts are times measured on the client and server clock respectively, then to convert the time tc to the servers time one has to compute tc+Δt and to convert a server time to client time one has to compute tsΔt

The above corollary is important because we cannot measure the elapsed time unless two times are measured on the same clock.

Elapsed Time
Suppose that t1,t2R0 are two times measured on the same clock , then the amount of time between the two is given by |t2t1|

Note that if t1t2 this equation is simply t2t1

Isolating for Travel Time and Clock Delta From Packets
Suppose that a packet is sent from the client to the server it is sent at client time c1 and received at server time s1, after a slight delay it sent back from the server at time s2 and received on the client at client time c2 then Δc=(s1c1)(c2s2)+Δt2 and Δt=(c2s2)(s1c1)+2Δc

The above proposition is good, but we can't isolate exactly Δc or Δt we need one to compute the other. This is when approximations start to come in, we will build up an approximation of the travel and clock delta. For each of the symbols we've mentioned let the same symbol above it with a bar represent the approximation of it, for example Δc is the approximation of Δc, additionally this process will be iterative, and so we'll denote the approximation after the i-th update as Δci

In order to make this process tractable, we'll start by assuming that Δt0=0 which is not a horrible assumption to make, which allows us to compute that Δc0=(s1c1)(c2s2)+02

But the above equation also has some problems too, recall that c1,s1,s2,c2 is just a sampling of a single full pass, and since we are now on the live network there is going to be variance between any two different passes. In order to account for this, we'll average out the values in question, to kickstart this process we'll need better variables, so let csi,sri,ssi,cri denote the i-th client send, server receive, server send, and client receive times all on their own clocks respectively.

With that in place, we set up the following system, the client starts by sending a packet with its current time to the server, this is the "send time" denoted by cs0 then the server receives the packet and gets the time which is denoted by sr0, then the sever waits for some fixed time duration which we wil denoted by w and measured in seconds (to slow down the frequency of the ping/pong) and gets a new time, which is denoted by ss0 and sends (sr0,ss0) to the client.

When received the client stores the value cr0 somewhere and then puts the value sr0cs0 into a ring buffer which we will denote by RBcs which represents the a collection of time differences between the client send and server receive, note that the values stored are not actually the travel time from the client to the server because the two times are not measured on the same clock.

RBcs will have some fixed size which we will assume to be 1000, additionally there will is another ring buffer RBsc of the same size in which will store cr0ss0. To simplify things we make the behavior of the server identical to that of the client, the benefit being that it spreads out the work-load between two computers meaning twice the number of iterations can be done in the same time.

For clarity after the value is added to the ring buffer the client then waits for w seconds and then measures cs1 and sends (cr0,cs1) to the server, then the server adds cr0ss0 and the process restarts. The ping and the pong continues until the ring buffers are full, which will first occur on the client because the server only starts adding to the ring buffer after its first receive, which occurs after the clients first receive.

Once the ring buffers are full, we take the average of the ring buffers, on the client when we take the average of RBcs it is given by this equation: srcs:=i=0999(srm+icsm+i)1000 and crss:=i=0999(crm+issm+i)1000 for some mN0, the purpose of m is to just denote that the index may not start at 0 because after more than 1000 client receives the ring buffer removes some of the beginning elements.

Now looking back to our initial value for Δc0 we will use these averaged values instead to say that Δc0=(srcs)(crss)+02 which will help with the variance between individual network send and receive events.

Now that we've computed an initial value for Δc0 we can use this to come up with an expected arrival time for the next packet we send to the server. Right before we send the packet, we get our current time

Now that we know Δc0 we can compute Δt1=crsssrcs+2Δc0 The order of computation will be Δt0Δc0Δt1Δc1 and so on each iteration we will first compute Δti and then use that to compute Δci.

Now that the process has been bootstrapped we will continue updating our ring buffers so that crss,srcs are still a smoothed version of the current travel times, and at each iteration we first compute