网络客户端-服务器消息交换和时钟同步帮助


10

我正在做一个快节奏的物理游戏,它是桌上曲棍球。有两个槌和一个冰球。游戏运行在iPhone / iPad上,我正在通过GameCenter做多人游戏。

这就是网络系统的工作方式。带有匹配标记的客户端将作为服务器进行结算,接受匹配请求的将是客户端。

“服务器”具有物理功能,响应是即时的,客户端也具有物理功能,因此在消息交换之间看起来很流畅。我作为服务器的工作是,我将客户的冰球速度和位置发送给客户端,客户端调整与服务器有关的冰球速度/位置以使其保持同步。否则,物理场将失去同步,并且将其拧紧。

当网络延迟很好,在100毫秒以下时,效果很好,我在客户端获得了流畅的可玩游戏,并且怪异的行为降到了最低。当滞后时间约为150到200毫秒时,就会发生此问题。在那种情况下,发生了我的客户冰球已经碰到边缘和反向的情况,但是它收到了来自服务器的延迟消息,并且它后退了一点,从而引起了对球行为的怪异感觉。

我已经阅读了一些有关它的内容:

傍网示例

单击同步示例

维基百科上的时钟同步

那么,我该如何解决呢?据我所知,最好的选择是使用时间戳在服务器/客户端上进行时钟同步,这样当我收到与时钟相关的延迟消息时,我就忽略了,然后让客户端模拟执行工作。你们同意吗?而且由于我发送的数据不可靠(UDP),所以我可能会收到延迟的消息或混乱的消息。

如果那是最好的方法,我如何实现时钟同步。我已经阅读了有关如何操作的步骤,但我不太了解。

它说:

  1. 客户端在“时间请求”数据包上标记当前本地时间,然后发送给服务器。
  2. 服务器收到后,服务器会在服务器上盖章并返回
  3. 客户端收到后,客户端从发送时间中减去当前时间,然后除以2以计算延迟。它从服务器时间中减去当前时间,以确定客户端-服务器时间增量,并加上半延迟以获取正确的时钟增量。(到目前为止,此algothim与SNTP非常相似)
  4. 客户重复步骤1至3五次或更多次,每次都暂停几秒钟。在此期间可能允许其他流量,但应将其最小化,以获取最佳结果。数据包接收的结果将被累积,并以最低延迟到最高延迟的顺序进行排序。中值等待时间是通过从此有序列表中选择中点样本来确定的。
  5. 丢弃与中位数相差大约1个标准偏差的所有样本,并使用算术平均值对其余样本取平均值。

按照这个例子,我会有这个:

让我们假装游戏已经加载并且我的客户端时间现在是0,所以我向服务器发送我的时间是0。

消息需要150毫秒才能到达服务器,但是服务器的时钟已经启动,并且比客户端提前1秒。服务器收到消息后,时间将是:1.15并将该时间发送给客户端,我们还好吗?假设我们的滞后时间恒定为150ms。

现在客户端接收时间1.15,并从发送的时间中减去当前时间,然后除以2以计算延迟。Wich为:0.3-0 = 0.3 / 2-> 150ms。

它从服务器时间中减去当前时间以确定客户端-服务器时间增量,并添加半延迟以获取正确的时钟增量:
客户端时间:0.3服务器时间1.15
0.3-1.15 = .85 +等待时间(.15)= 1

如何同步?我想念什么?

这是我第一次玩多人游戏和网络游戏,所以我有点困惑。

谢谢。


好问题。您能更正吗:0.3-1.15为1.15-0.3?
Ciaran

Answers:


12

发布的算法是正确的,但是在您的示例中,您忘记了服务器数据包到达客户端所花费的时间,因此:

Server time: 1
Client time: 0
Client sends 0 to server

... 150ms to get to server  (ping is 300! not 150ms in this case. Ping is round-trip)

Server time: 1.15
Client time: 0.15
Server receives packet and sends client 1.15

... 150ms to get back to client

Server time: 1.30
Client time: 0.30
Client receives 1.15 from server

现在您可以看到,如果客户端将时钟更改为1.15,则它将比服务器晚0.15,这就是为什么您必须调整Ping(又称往返时间[RTT])的原因。这是通过许多步骤完成的完整增量时间计算:

Server Time - Current Time + Ping / 2
= Server Time - Current Time + (Current Time - First Packet Time) / 2
= 1.15 (Perceived, not actual!) - 0.30 + (0.30 - 0.00) / 2
= 1.00

这为我们提供了1.00秒的正确增量时间


我得到了它,所以我的客户时钟是1.00,服务器是1.30。从服务器收到消息后,我是否必须添加ping来检查消息是否晚了?另一件事,如果延迟发生变化,我是否必须一直保持这些计算呢?
gmemario 2011年

1.00秒的增量时间将添加到当前时钟中,以使客户端时间等于服务器时间。延迟总是在变化,每个数据包的RTT会略有不同。在像游戏这样的短时间内,我只需将此时间同步一次,客户端就可以很好地猜测服务器的时间,并且两个时钟应该以大约相同的速度前进。唯一的例外是,如果您收到的数据包似乎来自将来。在这种情况下,有两种解决方案:1)进行新的时间同步。2)提前调整时钟以匹配未来的时钟
John McDonald

好的,让我们看一下这种情况,以确保我明白了:服务器时间:1s客户端时间:0s 150ms到达服务器服务器时间:1.15s客户端时间:0.15s服务器发送客户端1.15s 200ms到达客户端因此,我的ping现在是350ms。那是对的吗?服务器时间:1.35客户端时间:0.35执行计算:1.15-.35 +(0.35-0.00)/ 2现在,我的deltaTime = 0,975如果我将增量​​时间0,975添加到我的.35中,我得到:1,325 Wich有点不同步。那是正确的吗?
gmemario 2011年

@吉尔森,那是正确的。如果两个数据包的延迟时间不同(几乎可以保证),则客户端的增量时间计算将不是完美的。客户无法做到完美。在问题中描述的算法中,增量时间被计算了很多次,并且有一种方法可以选择和平均这些结果。许多时间同步方法会执行类似的操作,但是它们通常用于关键业务和长期运行的服务器,例如证券交易所。对于您需要短时间比赛的时间准确性,我认为这是过大的。
约翰·麦当劳

@Gilson,只要客户端对服务器的时间有一个合理的估计,并且两个时钟都以大致相同的速率前进,那么您就不会注意到任何问题。当客户端或服务器向另一端发送操作时,它们将发送其本地时间。在接收方,该消息应该始终是过去的,并且需要将其解释为过去的事件。这意味着您需要数据包中的所有信息,例如位置,速度(幅度+方向)和时间。然后,您可以将圆盘放在此处,然后将圆盘从过去移到现在。我在聊天中
约翰·麦克唐纳
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.