服务端学习一:Warzone服务端研究

来源:互联网 发布:我是歌手 知乎 编辑:程序博客网 时间:2024/06/06 11:05

今天看了一下国外的开源游戏Warzone ,想学习一下别人的服务端,就顺带翻译了一下他的网络方面的文档;如下


战地2100游戏中的网络相关代码使用TCP来实现对战网络,它可以由一个中转枢纽或者服务器来重新分配来自其他主机的消息数据(代码见:[source:lib/netplay/netplay.cpp@master lib/netplay/netplay.cpp])。每个主机都会对传到自己机器人和结构的指令负有责任,并且将自己的指令队列里面的消息转发转发给其他主机(指令队列:一个NET_SHARE_GAME_QUEUE message);


在所有客户端上,所有指令都会以相同的顺序执行相同的游戏逻辑时间,所以所有客户端的状态是相同的。状态信息通过syncDebug()函数打印出来,每个游戏时间片打印出来的状态的循环冗余校验码都会在网络中互相传递([source:lib/gamelib/gtime.cpp@master lib/gamelib/gtime.cpp] 中的 GAME_GAME_TIME )。如果某个时间片的消息没有按时送达,则游戏必须暂停(可能会增大指令发送和指令处理之间的公共延时来填补之后网络的滞后)。每个客户端的CRC冗余码都会进行比较来确认所有的客户端都有相同的游戏状态。


如果客户端没有相同的游戏状态,所有玩家已发出的打印的状态会被保存(在通过网络自动转发给你之后。)。项目里还有一些老的同步代码打算再次同步游戏状态如果客户端没有回复同意([source:src/multisync.cpp@master src/multisync.ppc]中),(在2.3以及之前的版本,游戏状态从未同步,所以这段代码曾经需要), 但是再次同步的代码实际上没有太大的用途,在未来可能会移除。


如果游戏客户端不知何故变得不同步,游戏状态的打印数据保存在~/.warzone2100-master/logs/desync[TIME]_p[CLIENT].txt中([TIME]是游戏逻辑时间,[CLIENT]是玩家数量)。为了查明为什么会不同步,会对之前的文件和不同的客户端进行对比(要确保对比的不是上一次游戏的数据),通过对数据逐一对比来找出哪个打印数据是错乱的源头。希望能通过它来猜测出导致这个不同数据的原因,并且解决它。


诸如炮弹之类的东西的数据不会通过网络进行转发。相反,每个玩家处理每个游戏物件并且计算出诸如物件哪里会着火,并在那个方向发生炮弹。由于每个客户端都有相同的代码和相同的数据,他们将在同一个目标上着火(在2.3版本及之前版本,这些话不完全正确,没有人会再谁向射击上达成共识)。每个对象有针对性的检查打击和毁灭,如果毁灭了,所有客户端都知道并且不需要发送任何网络消息。


战地2100这款游戏曾经被设计的让游戏开始时获得东西非常轻松,在发送决定给其他主机时也没有任何的数据封锁或者权限要求。预测错误并且尝试在检查阶段改正。正如你猜测的那样,这倒是了很多怪异事情的发生,没有人确认坦克在哪里,随机坦克随机爆炸,每个人都以为大家在作弊。


有很多东西需要在网络代码中进行改进:

1、TCP 连接枢纽模型不是特别的稳定有效,也就是说如果主机崩溃了,其他客户端也会随之崩溃。但是常理来讲应该每个客户端都要尝试连接其他客户端并且在另一个枢纽崩溃的情况下继续尝试连接。

2、用TCP取代UDP使得实现变得简单了许多,但是大多数的游戏使用P2P分布式决策系统或者使用UDP以达到快速传输和低开销的目的。

3、应该有一个玩家掉线重新连接的逻辑。