前言:
网络同步属于游戏开发中比较重要且复杂的一部分,但是由于网上的资料内容参差不齐,很多人直接拿别人的结论写文章,导致很多人对这一块的很多概念和理解都是错误的。本文参考了大量的相关论文和资料(超过三十篇),从网络同步的基本概念讲起,进一步深入到服务器架构与同步算法的实现细节,可以帮你系统的梳理网络同步技术的发展与应用。本篇核心内容为“网络同步的理解与网络架构的发展”,首发在网易雷火的知乎账号上。
注:在公众号后台回复“网络同步论文”可获取文中所引用的论文
目录(第一篇):
一.网络同步概念理解
二.网络架构与传统同步
1.网络游戏架构的发展
2.传统同步面临的问题
一.网络同步概念理解
网络游戏是电子游戏中一个极为重要的品类,自网络诞生以来,游戏行业就没有停止过对多人游戏玩法的探索。但是随着技术的发展,我们发现游戏服务器的架构发展却与通常的WEB服务器架构渐行渐远。在我看来,导致二者差异化的一个重要原因就是现代游戏服务器(更准确的说是游戏逻辑服务器)对网络同步有着很高的即时性要求。
那什么是网络同步呢?虽说是游戏中常用的概念,但其实任何与互联网有关的技术都需要网络同步,我这里会尝试用通俗易懂的方式循序渐进的给大家讲解其原理和概念。在其他领域,我们也许可以称他为“数据同步”,比如说用户A用他的手机点击按钮注册了一个QQ账号,那么他的手机号等个人信息就会被存储到服务器上面,这就是一个数据同步的过程。在这个过程中,数据由A的手机流向了QQ的官方服务器。对于游戏来说,其实原理也是一样,不过由于游戏中玩家关注的是游戏的视觉效果,所以我们不仅要同步数据,还要同步表现。可以简单认为,网络同步 = 数据同步+表现同步,数据同步是后端操作,而表现同步就是让前端对后端同步过来的数据进行进一步的处理从而达到表现上的一致。所以这样看来,不仅是游戏,任何拥有前端的产品都是这样的,比如浏览器、各种手机App,当你点击登录的时候,服务器就会要同步的个人信息发给你,并显示在界面上,你用任何一款手机显示的内容都是一样的。
不过一般Web服务器只是单纯的从服务器向客户端进行数据同步,不会把其他客户端的数据都发给你。而在游戏里面,你需要让N个客户端的显示看起来一模一样(由于网络延迟,同一时刻不可能完全一样),所以需要把其他玩家的一些数据也发给你,不能说A玩家跳了一下,B玩家看到A却趴下了,那样游戏就没法玩了。对于大部分的互联网产品,针对的都是个人用户的,并不需要两个用户之间进行交互,所以也就不需要不同用户的客户端界面保持一致。也行讲到这里,你会拍案而起,“浏览器不久是这样的么?我们所有人看一个网页都是一样的”。没错,最早期的一批网络游戏就是在BBS上进行的,那时候以文字交流的模式进行多人交互,效果本质上和很多页游是非常相似的。假如XXX知乎大佬的页面是一个棋盘的样子,每个人都可以在其首页上面下一枚围棋,那么这不就是一个可以全民参与的围棋游戏么?页游大概就是这么一个原理。
然而,前面我们还忽略了一个游戏中非常重要的需求(尤其是在MMO、FPS这种类型的网游中)——那就是实时性。你可以容忍微信点进去一个文章要花2秒钟,但是你不可能接受你的子弹要2秒后才打到敌人。实际上,在各种电子竞技里面,0.1秒的延迟就足以让整个游戏的局势发生逆转。像浏览器这种页面显示都吞吞吐吐的应用,如何用他流畅的玩FPS和MOBA呢?(关于云游戏这里先不谈)
到这里,我们再次梳理一下网络同步的概念。可以认为 网络同步 = 实时的多端数据同步+实时的多端表现同步。从计算机的角度来描述,网络同步是一个网络IO与CPU计算同样密集的游戏功能,他对主机CPU的性能要求较高,且单核的性能比并发更为重要。当然,游戏同步还有一些其他的特点,比如数据一般不要求存储、允许一定程度的丢失等,这里我们就不再进一步讨论。
了解以上网络同步的特点后,我们就可以进一步展开细节来说,比如传输的数据内容有哪些?数据的传递流向是什么样子的?我们平时口中常谈的“帧同步”,“状态同步”如何理解?为了能以一个更全面更权威的视角来讲解网络同步,笔者阅读了大量的论文和资料,对同步技术的发展和细节有了更为清晰的认识(很多内容与网上参差不齐的博客描述并不相同)。由于同步本身与服务器架构无法剥离,文章还会涉及到一些游戏网络架构的发展历史。
二、网络架构与传统同步
1.网络游戏架构的发展
1973年夏天,高中暑期实习生在美国加利福尼亚州NASA的研究中心首次撰写了游戏《迷宫战争》[1]。通过使用串行电缆连接两台算机,增加了两人游戏功能。由于涉及两台对等的计算机,可以使用相同的格式化协议包相互发送信息,因此可以认为这是第一个P2P架构的电子游戏。在那个时代,并没有多人在线游戏,互联网也没有诞生,网络同步一词更是无人知晓。不过当两台计算机上的数据进行传递时,最最最简单的同步模型就已经悄无声息的出现了,A把操作信息通过电缆发给B,B收到数据后处理,在把自己的操作数据通过电缆发送给A。比较有意思的一点是,计算机技术的发展或多或少都与电子游戏有着紧密的联系,甚至很多技术的诞生就是源于对游戏交互方式的探索。
1978年,Roy Trubshaw编写了世界上第一个MUD程序《MUD1》,后来又在此基础上诞生了开源的 MudOS(1991),成为众多网游的鼻祖。MUDOS使用单线程无阻塞套接字来服务所有玩家,所有玩家的请求都发到同一个线程去处理,主线程每隔1秒钟更新一次所有对象。这时候所谓的同步,就是把玩家控制台的指令发送到专有的服务器,服务器按顺序处理后再发送给其他所有玩家(几乎没有什么验证逻辑),这是最早的CS架构。当时PC图形化还不成熟,MUD早期的系统只有着粗糙的纯文字界面,由于也没有物理引擎等游戏技术,所以对网络延迟、反馈表现要求并不高。
大概在上世纪90年代,在P2P架构的基础上,很自然地诞生了以某个客户端为Host主机(或叫做ListenServer)的CS架构,这样的架构不需要单独都维护一个服务器,任何一个客户端都可以是Sever,能够比较方便的支持局域网内对战,也能节省服务器的运行与开发成本。不过,虽说也是CS架构,如果Host主机不做任何server端的校验逻辑,那么其本质上还是P2P模型,只不过所有的客户端可以把消息统一发送到一个IP,Host再进行转发,这种方式我们称其为Packet Server。
后来一些游戏团队(比如id software)又对CS架构做了进一步调整,先是将大部分的逻辑处理移到服务器上(服务器可能是一个独立的无窗口的后台程序),客户端只负责渲染。随后为了对抗网络延迟提升客户端的流畅性,又把一部分逻辑交回给客户端本地预执行,最终成为很多经典游戏和引擎的架构方式。
在2000年后,Eric Cronin的团队在传统多服务器的架构上[2]提出来镜像服务器模型[3]。这种模型提供了多个服务器的拷贝,避免单点崩溃影响到所有玩家的问题。类似CDN,玩家还可以选择就近的服务器进行通信,降低了通信延迟。不过,这种方式增加了服务器的租用和维护成本,在后续的游戏网络架构中并没有被大量使用,倒是WEB服务器广泛采用这种模型并不断将其发扬光大。
再后来,游戏服务器架构不断发展。游戏存储负载和网络连接负载随后从逻辑服上拆分出来,形成独立的服务;玩家数量增多后,又将游戏拆分成多个平行世界,出现了分服和跨服;游戏逻辑进一步复杂后,又开始按照功能去划分成网关服务器、场景服务器、非场景服务器等。我们今天讨论的网络同步几乎都是在逻辑服务器(基本上无法拆分)上进行的,所以后续的这些架构方式与网络同步的关系并不是很大,这里就不再赘述。
2.传统同步面临的问题
大部分的网络同步技术最早并不是诞生在游戏中,而是出现在各种计算机模拟仿真系统中。在70,80年代就有很多实验室针对Computer Simulation研究各种复杂且有效的同步手段(interactive simulation),我们后面提到的很多游戏同步算法[11]都是由这些早期的研究发展过来的。
网络游戏刚出现的时候,大部分还属于弱交互游戏,可以将其简单理解为一种回合制游戏。在每个回合开始时,所有玩家一同思考并把相关操作指令信息发送给其他玩家,其他玩家收到了别人的消息后就会在本地处理然后结束当前回合,如果没有收到就会进入无限期的等待。由于每个回合有比较长的思考和操作时间,所以网络延迟可以忽略不计,只要保证在回合结束的时候,所有玩家的状态的数据保存一致即可。这种游戏采用的同步方式与计算机网络中的停等协议(stop-and-wait-type)非常相似,是一种很自然也很简单的同步模型。不过由于当时网络同步并没有形成体系,所以这种同步方式也没有名字。在局域网盛行以及玩家数量较少的条件下,这种同步方式与架构都是可行的。
不过随着游戏的种类和玩法复杂性的提升,面对的问题也接踵而来。
在CS架构下逻辑在客户端执行还是在服务器执行?如果逻辑都在服务器执行,那么客户端的操作都会被发送到服务器运算,服务器计算出结果后通知客户端,客户端拿到结果后再做表现,这样的好处是所有的逻辑由服务器处理和验证,客户端无法作弊,但坏处是会造成客户端的资源被浪费,服务器运算压力过大。如果逻辑在各个客户端执行,那么玩家可以在本地计算后再把本地得到的结果告知服务器,服务器只进行简单的转发,这样的好处是玩家的本地表现很流畅,但坏处是很容易在本地进行作弊。而对于P2P架构,反作弊更是一个严重的问题,我连一个权威服务器都没有,根本无法验证其他客户端消息的真伪,怎么知道其他玩家有没有作弊?
我们要发送什么数据来进行同步?如果发送每个对象当前的状态,那么如果一个游戏里面有大量的角色,就会大规模的占用网络带宽,造成数据拥塞、丢包等等问题。如果发送玩家指令,那这个指令是要服务器执行还是服务器转发?而且对于大型多人在线游戏又没必要处理所有不相关的玩家信息,同样浪费网络资源
面对日益成熟的计算机网络协议,我们选择哪种来进行同步?TCP、UDP还是Http?
这时,游戏开发者们需要面对“发什么数据”,“在哪计算”,“发给谁”等细节问题,他们开始考虑引入更多的其他相关领域的技术(比如计算机模拟仿真)来解决游戏中的同步问题,网络同步概念初见端倪。
— 未完待续 —
游戏开发那些事
回复"gamebook",获取游戏开发书籍
回复"C++面试",获取C++/游戏面试经验
回复"操作系统",获取操作系统经典书籍
游戏开发交流群(875867499)
往期热门文章:
如何学习大型项目的源码?
史上最全的C++/游戏开发面试问题总结
游戏中的角色是如何“动”起来的?
参考文献:
[1]WIKI "History of video games". Available:https://en.wikipedia.org/wiki/History_of_video_games[Accessed: 2020-03-24]
[2]T.A. Funkhouser.”RING: A Client-Server System for Multi-User Virtual Environments“, In Proc. 1995 Available:https://dl.acm.org/doi/pdf/10.1145/199404.199418[Accessed: 2020-03-24]
[3]Eric Cronin, Burton Filstrup Anthony R. Kurc, Sugih Jamin,"An Efficient Synchronization Mechanism for Mirrored Game Architectures", 2004. Available: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.87.6043&rep=rep1&type=pdf[Accessed:2020-03-24]
— 觉得不错就点个在看吧 —