// Executed at the client when we receive a Pong message // find out how long it took since we sent the Ping // and update time offset internal void OnClientPong(NetworkPongMessage msg) { double now = LocalTime(); // how long did this message take to come back double newRtt = now - msg.clientTime; _rtt.Add(newRtt); // the difference in time between the client and the server // but subtract half of the rtt to compensate for latency // half of rtt is the best approximation we have double newOffset = now - newRtt * 0.5f - msg.serverTime; double newOffsetMin = now - newRtt - msg.serverTime; double newOffsetMax = now - msg.serverTime; offsetMin = Math.Max(offsetMin, newOffsetMin); offsetMax = Math.Min(offsetMax, newOffsetMax); if (_offset.Value < offsetMin || _offset.Value > offsetMax) { // the old offset was offrange, throw it away and use new one _offset = new ExponentialMovingAverage(PingWindowSize); _offset.Add(newOffset); } else if (newOffset >= offsetMin || newOffset <= offsetMax) { // new offset looks reasonable, add to the average _offset.Add(newOffset); } }
// executed at the server when we receive a ping message // reply with a pong containing the time from the client // and time from the server internal void OnServerPing(INetworkConnection conn, NetworkPingMessage msg) { if (logger.LogEnabled()) { logger.Log("OnPingServerMessage conn=" + conn); } var pongMsg = new NetworkPongMessage { clientTime = msg.clientTime, serverTime = LocalTime() }; conn.Send(pongMsg, Channel.Unreliable); }