游戏同步网络编程

网络游戏同步技术概述

2019-02-13  本文已影响50人  DonaldW

主要内容

本文会就网络游戏同步技术进行概述,包括如下内容:


著名游戏网络同步方案汇总

下表为本人汇总的各著名游戏的网络同步方案,已尽力添加引用来源。
通过该表,读者可尝试思考:为什么他们会采取这样的方案?找找看有否什么规律?相信看完下文,应该可以找出答案。
注,本文的锁步同步(Lockstep)特指只同步操作的确定性锁步同步(Deterministic Lockstep)。本文不讨论快照同步(Snapshot Synchronization、Snapshot Interpolation),认为其等同于状态同步(State Synchronization)。

Genre Game Year Network Transport Protocol Network Model Network Topology
RTS Age of Empires[11][12] 1990s UDP Lockstep Peer to Peer
RTS Starcraft I/II[11][12] 1990s UDP Lockstep Peer to Peer
RTS Warcraft I/II/III/Dota[11] 1990s UDP Lockstep Peer to Peer
MMORPG Ever Quest[9] 2000s UDP State Sync Client Server
MMORPG World of Warcraft[9] 2000s TCP State Sync Client Server
MMORPG Lineage I/II[9] 2000s TCP State Sync Client Server
MOBA League of Legends 2000s UDP State Sync Client Server
MOBA DOTA2 2010s UDP State Sync Client Server
MOBA(Mobile) 王者荣耀 2010s UDP Lockstep Client Server
MOBA(Mobile) 全民超神 2010s UDP State Sync Client Server
FPS Doom I/II[11] 1990s UDP Lockstep Peer to Peer
FPS Quake I/II/III[11][12], Counter Strike 1990s UDP State Sync Peer to Peer
FPS HALO: REACH Campagin and Firefight Mode[10] 2010s UDP Lockstep Peer to Peer
FPS HALO: REACH Multiplayer Mode[10] 2010s UDP State Sync Peer to Peer
FPS Battlefield[8], Call of Duty[8][12], CS:GO[8] 2010s UDP State Sync Client Server
FPS(Mobile) 穿越火线:枪战王者 2010s UDP State Sync Client Server
FPS(+MOBA) Team Fortress, Overwatch[4], Paladins 2010s UDP State Sync Client Server
FPS(+BattleRoyale) PUBG, Fortnite 2010s UDP State Sync Client Server
FPS(+BattleRoyale)(Mobile) 绝地求生:刺激战场, 绝地求生:全军出击 2010s UDP State Sync Client Server
RAC Watch Dog 2[6] 2010s UDP State Sync Peer to Peer
RAC Rocket League[7] 2010s UDP State Sync Client Server
ACT For Honor[5] 2010s UDP Lockstep Peer to Peer
FTG Street Fighter IV/V[8] 2010s UDP Lockstep Peer to Peer
FTG Tekken 7[8] 2010s UDP Lockstep Peer to Peer
CCG Hearthstone 2010s TCP State Sync Client Server

网络传输协议(Network Transport Protocol)

本文中的网络传输协议(Network Transport Protocol),主要是指UDP协议和TCP协议。
在TCP/IP协议族(互联网协议套件,Internet Protocol Suite)中,UDP和TCP位于传输层(Transport Layer),它俩都独立依赖于更底一层网络互连层(Internet Layer)中的IP协议(网际协议,Internet Protocol)。

Berkeley套接字(Berkeley Sockets)是进行UDP或TCP通信的标准API,属于POSIX标准,所以Socket、Berkeley Socket、POSIX Socket、BSD Socket,都指同一个东西。
通过Socket这个类及其方法,很简单就能进行UDP或TCP通信。

通过分析协议报头(Header),可快速精确知道该协议增加了哪些功能。

UDP报头如下,


UDP报头

UDP在IP之上,增加了端口(Port)的概念,收发双方从而能通过约定好的几个端口来进行不同功能的通信;增加了校验和以增加了一定的校验能力。
所以也能看到UDP其对于网络游戏来说,和IP几乎有很相似的特性:

TCP则复杂很多,TCP的报头如下,


TCP报头

除了也有端口、校验外,TCP主要额外提供了:

TCP本身足够复杂,本文并不能细究他们的具体原理,仅简述和网络游戏同步相关的特性:

综上所述,大多网络游戏采用UDP。
TCP更加适用于回合制等慢节奏游戏,如炉石传说等。
另魔兽世界使用了TCP,且取得了辉煌的商业成功,故也有不少MMORPG也使用TCP,尽管如此,未见得TCP是最好的选择。[9]


网络同步模型(Network Model)

最主要的网络模型是:锁步同步(Lockstep)状态同步(State Synchronization)

本文针对“帧”有以下两种术语定义:
逻辑帧,在本文会被称为Tick,游戏在逻辑层面是离散的过程,即可以认为是一个逻辑帧一个逻辑帧地进行逻辑运算,逻辑帧号是指游戏逻辑层面当前处于第几帧;
渲染帧,在本文会被称为Frame,游戏在画面呈现层面也是离散的过程,即可以认为是一幅画面一幅画面地呈现给玩家的,渲染帧号是指游戏当前呈现的是第几幅画面;
游戏的逻辑帧率和渲染帧率是互相独立的,比如一个游戏可以是20帧每秒的逻辑帧率、60帧每秒的渲染帧率。

游戏逻辑是一个逻辑帧一个逻辑帧地持续离散进行的,可以抽象为:


游戏在第0个逻辑帧时,根据玩家信息P和游戏配置C,进行初始化运算g,得出初始化状态S0
游戏在第k个逻辑帧时,根据前一个状态Sk-1和游戏配置C,然后接受所有外部变化因素Ik,进行逻辑t运算,得出第k个逻辑帧新的游戏状态Sk
游戏外部变化因素Ik是状态变化的原因,往往是各个玩家操作。

锁步同步的本质是只同步游戏外部变化因素Ik,状态同步的本质是只同步游戏运算得出的结果状态Sk

注,本文的锁步同步特指只同步操作的确定性锁步同步(Deterministic Lockstep)。本文不讨论快照同步(Snapshot Synchronization、Snapshot Interpolation),认为其等同于状态同步。

网络同步模型简史

1990年代便已有针对每一步(step、turn)进行停止等待(stop-and-wait-type)的网络同步方式,即客户端一步一步地把自己的信息发给其他客户端,这些信息可以是客户端的本地网络对象的状态,也可以是玩家操作[13][14]
同期,P2P(见下网络拓扑结构一节)是更为盛行的网络连接拓扑结构。但P2P的停止等待同步方案有lookahead-cheating类型的外挂,比如使用外挂的客户端A在第k步时故意等到别人的第k步信息都到达了之后,才进行逻辑运算并发送自己的第k步信息,等于客户端A总是偷窥别人的游戏决策之后才作出自己的决策,从中获取到不公平的先手利益。
所以,2001年,Nathaniel Baughman和Brian Neil Levine在此基础上,提出锁步同步(Lockstep)[14]以对抗该外挂。每个客户端在发送第k步的明文信息之前,先针对明文信息进行加密计算生成“预提交哈希值(commitment hash)”并发送给其他客户端,待客户端接收到第k步的所有客户端的预提交哈希值之后,才发送自己第k步的明文信息给其他客户端,等到收到所有其他客户端的第k步明文信息后,本客户端为这些明文信息逐一生成明文哈希值并和预提交哈希值对比,如果发现客户端B的明文哈希值和预提交哈希值不等,则代表客户端B是外挂。
至此,锁步同步是既可以同步客户端玩家操作、也可以同步客户端权威网络对象的状态。所以也并不要求确定性。
然后,同样也是2001年,Mark Terrano和Paul Bettner在帝国时代(Age of Empire)游戏中为了解决游戏中海量网络实体的问题,基于锁步同步,方提出了确定性锁步同步(Deterministic Lockstep)[15],即每一步同步的,仅仅只有玩家操作数据,而不包含网络对象数据。

另外,1999年,Christophe Diot和Laurent Gautier提出了Bucket Synchronization[13],即把时间按固定时长(约40ms)划分为Bucket,该时长内的数据归属于该Bucket。在一开始时有一个较长的播放时延(Playout Delay,约100ms),用于等待其他客户端的Bucket数据传输到达。没及时到达的数据不会被直接应用,但也可以保存起来用于可能发生的外插(Extrapolation)比如航位推测(Dead Reckoning)。
其Bucket,事实上即逻辑帧(Tick)的概念。

Bucket Synchronization
最后,2003年,Ho Lee等人针对上述锁步同步的每一步的时延都较大的缺点进行优化,借鉴Bucket Synchronization,提出了Pipelined Lockstep[16]

至此,现在为大家所理解的:操作同步、不等待超时玩家的操作的确定性锁步同步,终于成型。
总而言之,每一步都停止等待的网络同步很早就有,却缺个简短的名字。为了安全性提出的“Lockstep”方案使用广泛,逐渐成为停止等待同步的代名词。翻译成中文时,引入了时间帧的概念Bucket Synchronization也和Lockstep已经结合起来使用,便将“step”译为帧,称为“帧同步”。然后更狭义的确定性锁步同步用得越来越多,大家也逐渐把“Deterministic Lockstep”简称为“Lockstep”,所以,确定性锁步同步口头交流中更常被简称为“帧同步”,有时也会被称为“操作同步”。

所以,本文也把确定性锁步同步简称为锁步同步。

锁步同步(Lockstep)

因为锁步同步只同步变化的原因Ik,所以要求各个客户端的运算逻辑gt是严格确定性(Deterministic)的,所有客户端才能算出严格一致的结果Sk。如果在计算过程中包含了一丝不确定的因素,即会导致各个客户端运算Sk时有一丝的误差,那么接下来的逻辑帧误差会越来越大,导致蝴蝶效应,从而最终各个客户端看到的结果状态完全不一样了。
以著名锁步游戏王者荣耀为例,假设你的客户端和其他正确客户端已经发生不一致,其他玩家在正确客户端作出的合理操作,到达你已经状态不一致的客户端做逻辑演算时,却变得不一样的状态结果,这个结果很可能是不合理的,所以你很可能会看到其他玩家英雄都奇怪地乱跑,甚至跑到塔下送死,或者对着空气放技能,等。

游戏要做到严格确定性,须做好一些事情:

对锁步同步游戏来说,不同步造成的游戏体验是极差的,偶现的不同步问题是极为头痛的, 因此制定检测不同步的管线流程对锁步同步游戏来说是至关重要的,比如帧状态哈希对比、静态代码扫描分析、帧级别甚至函数级别的高性能日志、外网不同步率统计,等。

状态同步(State Synchronization)

因为状态同步只同步游戏运算得出的结果状态Sk,所以需要有机器来进行权威(Authoritative)的状态计算,并传输给其他机器,其他机器都将采纳接收到的状态。
本文只讨论权威机器只有一部的情况。视乎具体网络拓扑结构,这部权威机器会被称为服务器(Server)或主机(Host),其他没有权威的机器称为客户端(Client)。

所以,状态同步,口头交流中也常不太精确地被称为“CS同步(Client-Server)”。

包括Halo、Unreal、Unity、Overwatch等,几乎所有著名状态同步的技术实现,都最终参考了Mark Frohnmayer和Tim Gift于1998年发布的The TRIBES Engine Networking Model[1]一文进行实现。

状态同步开发过程中最基础也最重要的是,不管客户端网络对象当前处于什么状态,它都要做到能正确地完全退出旧状态,退出后不能残留旧状态的逻辑层效果,并正确地进入服务器告知的新权威状态,从而带来新状态的逻辑层效果。
也要避免以非状态同步的方式同步权威状态,比如服务器只传输Ik给客户端(而不传输Sk),让客户端在本地计算出网络对象的新状态Sk。这可能会带来服务器客户端之间状态不一致。比如某个网络对象在第k个逻辑帧发生了Ik从而进入Sk,且之后S都不再改变,那么服务器只会在第k帧才会发送Ik;之后若客户端因断线重连或实时死亡重播等原因导致该网络对象状态在客户端被重置为S0,但当前服务器逻辑帧已大于k,服务器不会再传输Ik给客户端,那么该网络对象在客户端里就错误地一直停留在S0了。

之前在锁步同步讨论到的确定性指的是“严格的”确定性。在讨论状态同步时,偶尔也会提及“不严格的”确定性(比如[4]的Q/A阶段最后一个问题),此类确定性只要求客户端服务器之间满足“足够的”确定性,以便客户端能够比较准确地进行预表现即可,因为客户端最终会采纳服务器的状态,修正累计的误差。

锁步同步和状态同步的对比

锁步同步 状态同步
流量 一般情况下较低,决定于网络玩家数目 一般情况下较高,决定于当前该客户端可观察到(Observable)的网络实体数目
预表现 难,客户端需本地进行状态序列化反序列化,进行Roll-Forth 较易,客户端进行预表现,服务器进行权威演算,客户端最终和服务器下发的状态进行调解(Reconciliation)和Roll-Forth
确定性 须要严格确定性 须要不严格确定性
对弱网络的适应能力 较低,因为较难做到预表现 较高,因为较易做到预表现
断线重连 较难,需比较耗时地进行快播追上实时进度的游戏状态 较易,服务器下发当前实时游戏状态的Snapshot即可
离线重播(比如播放录像文件) 较易,且重播文件大小较小(和流量相关) 较易,但重播文件较大(和流量相关)
实时重播(比如死亡重播) 难,视乎需求,客户端可能需要本地(性能消耗非常大地)每帧对进行全场状态序列化,从而能发序列化“回到过去”,并进行重播,播完后再(可能比较耗时地)快播追上实时游戏状态 较易,服务器下发历史Snapshot给客户端回到过去、下发重播数据进行重播、再下发当前Snapshot恢复实时游戏
网络逻辑性能优化 较难,因为客户端需要运算所有逻辑 较易,大部分逻辑默认是在服务器进行运算,从而分担客户端运算压力;服务器也可帮助客户端进行可观察网络对象的剔除(基于距离剔除、遮挡剔除、分块剔除等),也可以降低优先级低的物体或属性的同步频率,从而减小流量和再次减小客户端运算压力
大量网络实体时的流量情况 好,因为流量只决定于网络玩家数目 如果客户端可观察到的网络实体较少,则较好,比如PUBG等BattleRoyale类型;否则如果客户端可观测到的网络实体较多,则较差,比如Starcraft等RTS
大量网络实体时的性能情况 较差,因为客户端需要运算所有逻辑。如果大部分网络实体有“Sleep”的可能,则有优化空间 如果客户端可观察到的网络实体较少,则较好,比如PUBG等BattleRoyale类型;否则如果客户端可观测到的网络实体较多,则较差,比如Starcraft等RTS
外挂 因为客户端拥有所有信息,所以透视类外挂的影响会比较严重 也会有透视类外挂,但服务器会进行一定的视野剔除,所以影响稍小
开发特征 平时开发起来很高效,不需前后端联调,但写代码时需要确保确定性,心智负担较大,不同步bug如果出现,对版本质量是灾难性的 平时开发起来效率一般,需要前后端联调(LocalHost自测起来效率很高,但和最终Client-Server的真实情况不尽相同,自测应以后者为准,故依然需要联调),但写代码时不需确保确定性,心智负担较小,无不同步的bug
采用第三方库 较难,因为第三方库也须确保确定性 较容易,因为第三方库不须确保确定性

网络拓扑结构(Network Topology)

网络拓扑结构,是指参与游戏的机器的网络连接方式,主要包括对等结构(Peer-to-Peer,P2P结构)和主从结构(Client-Server,CS结构)。

P2P结构是网状结构(Mesh Topology),游戏中的P2P一般是全连接(Full Connected)的网状结构,如下所示。P2P结构中所有客户端两两相连,连接数为O(n2),地位平等,功能一致。

CS结构是星状结构(Star Topology),如下所示。CS结构有至少一部机器为服务器(Server),本文只讨论只有一部服务器或主机的情况,其和其他客户端为主从关系,客户端只和服务器连接,客户端之间不会相连,连接数为O(n)
当运行服务器的机器只用于逻辑运算游戏状态,只用于下发状态给客户端,和客户端完全分离的“Headless”机器时,该服务器称为Dedicated Server;当运行服务器的机器同时也在运行客户端运算,也被玩家所控制时,该服务器称为Listen Server,也称为Host。

两种网络拓扑结构的对比如下

P2P结构 CS结构
连接数 O(n2) O(n)
流量 各客户端相等,都为O(n2) 服务器为O(n),客户端为O(1)
客户端之间时延 较小,为RTT/2 较大,为RTT

网络同步模型和网络拓扑结构是不同的概念,所以它们的组合情况如下表所示,

P2P结构 CS结构
锁步同步 把本地机器玩家的操作广播给其他机器 把本地客户端玩家的操作发送给服务器,服务器再广播给所有客户端
状态同步 各个机器只对自己控制的角色有权威,向其他机器广播自己控制角色的权威状态 把本地客户端玩家的操作发送给服务器,服务器再把根据客户端的情况发送需要的网络实体的权威状态

网络环境质量

评估网络环境质量,主要包括时延(Latency)、丢包(Packet Loss)、带宽(Bandwidth)。
针对日常各种主要使用环境,有以下网络环境质量统计。

环境类型 平均时延(ms) 抖动时延(ms) 丢包率 上行带宽 下行带宽
正常网络 20 20 2% 90% 90%
普通弱网络 30 100~300 12% 80% 60%
超低网络 50 100~500 30% 60% 40%
繁忙网络 50~100 30~50 5% 25% 25%
交通工具行驶中 200~400 200~2000 5% 60% 60%
地铁中 200~400 200~2000 12% 60% 60%
基站切换中 3000~7000 2000 5% 60% 60%

网络时延主要有2种评估数值,PingRTT(Round Trip Time)
Ping,指网络连接的两个端之间的信号在网络传输所花费的时间,Ping描述了“两部机器之间的网络传输时延是多少?”。比如从A端操作系统发出信号时开始计时,到达B端操作系统并立刻返回响应信号,返回到A端操作系统后停止计时,该时长为Ping。
RTT,Round Trip Time,一般情况下可认为等于Ping,但在本文中,RTT = Ping + WaitTime + ProcessTime,即RTT包含了Ping、两个端的处理信号前的等待时间、两个端处理信号的时间,这样的RTT描述了“玩家实际体验到的游戏时延是多少?”。比如从A端游戏逻辑发出信号开始计时,在A端可能等待一段时间后,也可能处理一些其他逻辑后,方调用操作系统发出信号,经网络传输到达B端操作系统后,B端也可能有类似的等待时间和处理其他逻辑时间,也包括处理该信号本身的时间,然后才发出响应信号,响应信号经过网络传输到A端操作系统后,再来一些类似的等待处理时间,最终A端游戏逻辑接收到响应信号方结束计时,该时长为RTT。
Ping值和RTT值,对一般网络游戏而言,20ms为优秀,50ms为正常,100ms为一般,200ms为差。
4G网络自身时延约30ms~40ms,5G网络自身时延为6~10ms,骨干网在大陆内部互连时延约20ms。即4G时代4G接入本身是网络时延瓶颈,5G时代骨干网为网络时延瓶颈
上海与各国际城市的骨干网时延(ms)如下表,详情可参阅[17]。

北京 香港 东京 旧金山 悉尼 马德里 孟买 巴黎 纽约 伦敦 法兰克福 蒙特利尔
上海 27 33 57 168 254 300 578 256 237 258 248 227

网络丢包直接原因主要是因为无线网络和/或拥塞控制,但根本原因比较多元和复杂,故统计略。
对一般网络游戏而言,网络丢包率2%以下为优秀,5%为一般,10%以上为差。

对比传统应用,网络同步涉及到的带宽较小,正常情况下带宽不会成为网络游戏同步中的瓶颈(除非是云游戏:p)。
注意传统网络中网络带宽常见为b/s(Bit per Second),但本文采用B/s(Byte per Second)
一般锁步同步游戏需要2~4KB/s,快节奏状态同步游戏需要5~10KB/s。
常见网络游戏相关的网络带宽如下表[18][19]

网络连接类型 下行(B/s) 上行(B/s)
ADSL2 12K 1.4K
GPRS (2.5G) 7.2K 3.6K
Bluetooth 1.1 125K 125K
Bluetooth 5.0 6.25M 6.25M
LTE (4G) 21.6M 7.25M
IEEE 802.11n (aka Wi-Fi 4) 75M 75M
5G Spec 125M 125M
Gigabit Ethernet 125M 125M
IEEE 802.11ac (aka Wi-Fi 5) 850M 850M
10 Gigabit Ethernet 1.25G 1.25G

结论

本文就网络传输协议(Network Transport Protocol)、网络同步模型(Network Model)、网络拓扑结构(Network Topology)进行了系统性的介绍,并列举了一些网络游戏所选方案的情况,及方案对比。也介绍了网络同步的一些历史,和网络质量评估指标。

本文并未就实现原理进行细节介绍,未来将会以实际项目为例,介绍UDP、状态同步、Client-Server的技术细节。



引用

[1] Mark Frohnmayer, Tim Gift, "The TRIBES Engine Networking Model or How to Make the Internet Rock for Multi­player Games", 1998. Available: https://www.gamedevs.org/uploads/tribes-networking-model.pdf [Accessed: 2019-01-27]
[2] Glenn Fiedler, "State Synchronization Keeping simulations in sync by sending state", 2015, Available: https://gafferongames.com/post/state_synchronization/ [Accessed: 2019-01-27]
[3] Joshua Glazer, Sanjay Madhav, "Multiplayer Game Programming", Addison-Wesley, 2015.
[4] Tim Ford, "Overwatch Gameplay Architecture and Netcode", GDC, 2017.
[5] Xavier Guilbeault, Frederic Doll, "Deterministic vs Replicated AI Building the Battlefield of For Honor", GDC, 2017.
[6] Matt Delbosc, "Replicating Chaos Vehicle Replication in Watch Dogs 2", GDC, 2017.
[7] Jared Cone, "It IS Rocket Science! The Physics of 'Rocket League' Detailed", GDC, 2018.
[8] Battle(non)sense, "Netcode & Input Lag Analyses", 2017. Available: https://www.youtube.com/playlist?list=PLfOoCUS0PSkXVGjhB63KMDTOT5sJ0vWy8 [Accessed: 2019-02-08]
[9] Chen-Chi Wu, Kuan-Ta Chen, Chih-Ming Chen, Polly Huang, and Chin-Laung Lei, "On the Challenge and Design of Transport Protocols for MMORPGs". 2019. Available: http://www.iis.sinica.edu.tw/~swc/pub/tcp_mmorpg.html [Accessed: 2019-02-08]
[10] David Aldridge, "I Shot You First: Networking the Gameplay of HALO: REACH", GDC, 2011. Available: https://www.youtube.com/watch?v=h47zZrqjgLc [Accessed: 2016-07-02]
[11] Maksym Kurylovych, "Lockstep protocol", University of Tartu, 2008. Available: http://ds.cs.ut.ee/courses/course-files/Report%20-2.pdf [Accessed: 2019-02-11]
[12] Glenn Fiedler, "What Every Programmer Needs To Know About Game Networking A short history of game networking techniques", 2010. Available: https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/ [Accessed: 2019-02-11]
[13] Christophe DIOT, Laurent GAUTIER, "A Distributed Architecture for Multiplayer Interactive Applications on the Internet", IEEE, 1999. Available: https://www.cs.ubc.ca/~krasic/cpsc538a-2005/papers/diot99distributed.pdf [Accessed: 2019-02-12]
[14]Nathaniel E. Baughman, Brian Neil Levine, "Cheat-Proof Playout for Centralized and Distributed Online Games", IEEE INFOCOM, 2001. Available: https://pdfs.semanticscholar.org/2301/a3f35845baf350f65e17f6056868791854fe.pdf [Accessed: 2019-02-12]
[15] Mark Terrano, Paul Bettner, "1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond", 2001. Available: http://www.gamasutra.com/view/feature/3094/1500_archers_on_a_288_network_.php [Accessed: 2019-02-12]
[16] Ho Lee, Eric Kozlowski, Scott Lenker, Sugih Jamin, "Multiplayer Game Cheating Prevention With Pipelined Lockstep Protocol", 2003. Available: http://www.ekozlowski.com/assets/multiplayer-game-cheating-prevention.pdf [Accessed: 2019-02-12]
[17] "Internet Backbone Network Latency". Available: https://www.dotcom-tools.com/internet-backbone-latency.aspx [Accessed: 2019-02-15]
[18] "List of interface bit rates". Available: https://en.wikipedia.org/wiki/List_of_interface_bit_rates [Accessed: 2019-02-15]
[19] "5G", Available: https://en.wikipedia.org/wiki/5G#Performance_targets [Accessed: 2019-02-15]

上一篇 下一篇

猜你喜欢

热点阅读