2010-09-20 91 views
12

我正在爲我製作的遊戲添加聯網多人遊戲。當服務器向客戶端發送更新數據包時,我會包含一個時間戳記,以便客戶端確切知道該信息何時有效。但是,服務器計算機和客戶端計算機可能會將其時鐘設置爲不同的時間(甚至可能差幾秒),所以服務器的時間戳需要轉換爲客戶端的本地時間。測量聯網設備之間的時間差異

所以,我想知道計算服務器和客戶端之間時差的最佳方法。目前,客戶端在初始化過程中向服務器發送一個時間戳記,記錄了請求的發送時間和應答時間,並且猜測時間戳記大概是在旅途中途產生的。客戶也運行這些試驗中的10個,並取平均值。

但問題是,我得到不同的結果重複運行的程序。在每組10個測量中,每個測量很少會發生400多毫秒的偏差,這可能是可以接受的。但是如果我在程序的每次運行之間等待幾分鐘,結果平均值可能會有2秒鐘的不同意見,這是不可接受的。

有沒有更好的方法來找出兩個聯網設備的時鐘之間的差異?還是至少有一種方法來調整我的算法,以產生更準確的結果?

可能相關或不相關的細節:設備是通過藍牙進行通信的iPod Touch。我測量的平均值是50-200毫秒。我不能要求用戶同步他們的時鐘。 :)


更新:在下面的答案幫助下,我寫了一個Objective-C類來處理這個問題。我發佈在我的博客上:http://scooops.blogspot.com/2010/09/timesync-was-time-sink.html

回答

23

我最近在這上面花了一個小時的課,但時間還不夠長,但我會盡量讓它指向正確的方向。準備好一個小代數。

讓s等於根據服務器的時間。讓c等於根據客戶的時間。令d = s - c。 d是客戶的時間將其糾正到服務器的時間,這是我們需要解決的問題。

首先我們用時間戳從服務器發送一個數據包給客戶端。當客戶端接收到該數據包時,它將給定時間戳和它自己的時鐘之間的差值存儲爲t1。

客戶端然後用自己的時間戳發送一個數據包到服務器。服務器將時間戳和自己的時鐘之間的差異作爲t2發送回客戶端。

請注意,t1和t2都包括數據包的「行程時間」t加上兩個時鐘d之間的時間差。假設該旅行時間是在兩個方向上是相同的那一刻,我們現在有兩個未知數兩個方程,它可以解決:

t1 = t - d 
t2 = t + d 
t1 + d = t2 - d 
d = (t2 - t1)/2 

訣竅來,因爲旅行時間並不恆定,證明通過你的ping在50到200毫秒之間。事實證明,使用具有最短ping時間的時間戳是最準確的。這是因爲您的ping時間是「裸機」延遲加上在路由器隊列中等待的所有延遲的總和。每隔一段時間,一個幸運數據包就會在沒有任何排隊延遲的情況下通過,因此您將最短時間用作最可重複的時間。

還請記住,時鐘以不同的速率運行。例如,我可以將家中的電腦重置爲毫秒,一天之後它會變慢8秒。這意味着你必須不斷調整d。您可以使用隨時間計算的各種d值的斜率來計算漂移並在兩次測量之間進行補償,但這超出了答案的範圍。

希望能幫助你指出正確的方向。

+0

哇!謝謝!這正是我要找的。對我來說這並不完全清楚,但爲什麼這比我最初的方法更好(雖然我相信它),但是當我嘗試時我會回到這裏。我認爲我不需要在整個遊戲過程中進行調整,但如果需要的話,應該不難做到。再次感謝! – whooops 2010-09-21 00:19:56

+0

這工作得很好。我發現,如果我總是採用最小(即最負)的t1和t2值,這與採用最小的ping相同,所以它會收斂到正確的偏移量。 我已經 T1 =客戶郵票 - 服務器郵票 和 T2 =服務器郵票 - 客戶端郵票 另外,我發現,iPhone手機相當顯著漂移!在半小時內,兩臺設備之間的實際偏移可能會改變半秒鐘。我使用與NTP服務器聯繫的時鐘程序對此進行了驗證。 – whooops 2010-09-21 20:28:49

+0

很高興它對你有幫助。 – 2010-09-21 20:35:48

2

除非您可以使用某些統計方法,否則您的算法不會更準確。首先,10可能是不夠的。第一個也是最簡單的變化是收集100個運輸時間樣本,並將x最長和最短。

要增加的另一件事是兩個客戶端在每個數據包中發送自己的時間戳。然後你也可以計算他們的時鐘有多不同,並檢查時鐘之間的平均差異。

您也可以特別檢查STNP和NTP實現,因爲這些協議專門用於此目的。

+0

謝謝。我想我會嘗試上面的答案給出的算法,並採用多個樣本的建議。 – whooops 2010-09-21 00:23:03