没有合适的资源?快使用搜索试试~ 我知道了~
网游服务器编写需要注意的几个问题
5星 · 超过95%的资源 需积分: 10 25 下载量 28 浏览量
2010-07-03
14:35:49
上传
评论
收藏 83KB DOC 举报
温馨提示
试读
12页
这是我写的网游服务器编写要注意的几个问题。 虽然是几个问题,但是基本上是我这7,8年来写网络游戏服务器端遇到问题的总结和经验。
资源推荐
资源详情
资源评论
编写网络程序应该注意的几个问题
刘刚
2003 年 9 月 19 日星期五
2006 年 7 月 14 日星期五批注
2009 年 1 月 22 日修订
经过一年多来《天骄》网络游戏的编程工作,有了一些经验和教训,希望在这里跟大
家分享。
注:后来我和我的同事编写了天骄 II,增加了不少经验,在这里补上。以前我们得出
的一些结论到了现在发生了变化,在这里也进行了修正和补充。毕竟我离开目标软件和网
络游戏行业一年了,有些经验可以结合着具体的游戏表达出来。
网络程序与单机程序相比难度是成倍增加的
网络程序的编程和单机版相比,难度增加了许多,而且往往是超乎我们的想象的。
对稳定性需求增加
一台游戏的服务器程序需要持续不断的运行,至少要在 24 小时内不会发生任何问题。
这与单机游戏相比,难度增加了。如果希望这款游戏的规模再大些,要求就更高了。基本
上要达到电信级的水平。
注:在后来的天骄 II 里面,我们终于基本上做到无严重 BUG,正式运营的游戏服务器
可以正常运行一周没有问题,在我们自己的测试服务器上运行时间超过 49 天。当然这个成
绩在我离开目标的时候还没有达到,还存在一个 BUG 不定期的会导致崩溃,这时候是去年
的 7 月份,天骄 II 收费 2 个月。后来在去年年底,这个 BUG 由接替我工作的同事们找到,
值得庆幸的是,导致 BUG 的代码并不是我们编写的,而是编写网络底层的程序员编写的。
这说明我们在防止 BUG 方面,做得很不错。
对效率要求增加
一台服务器支持的游戏人数是非常多的,每个用户的操作也是多种多样的。中间会有
慢速操作和快速操作。就需要我们分离这些操作,提高快速操作的效率,而不能让这些操
作为了等一些无关紧要的东西而降低效率。对这部分内容进行优化势必会增加程序的复杂
性和出现问题的可能性。
注:一般我们会用多线程来充分利用服务器上的多个 CPU。
程序复杂度增加
游戏的用户操作比起那些电信的操作来说要复杂的多了。所可能导致的问题也要多很
多。服务器结构的扩充,程序内部模块的划分,模块和线程之间的交互都会使得程序更加
容易出现 BUG,而且这些 BUG 更加隐蔽。
注:服务器程序的复杂度,不在于代码量的多少,而在于代码的 BUG 数量和优化的程
度。
版本更新频繁
天骄的服务器程序从 2003 年 2 月 14 日至今就更新了 123 个版本,平均不到每两天就
1
有一个版本。每次更新都可能包含新的 BUG,新的问题。
长时间的维护,同一段代码由不同的人维护,也会增加代码中的隐患。
注:所谓的至今是只截止到我写这篇文字的时候,2003 年 9 月,大约 7 个月的时间。
天骄 I 至今还在运营,后来更新了多少版我没有统计过。
对错误的处理比对功能的实现更重要
实现功能,当然是程序的主要用途。但是对于服务器程序,我们不光要实现功能和用
途,而且要在出现错误的时候还能健壮的处理(对于健壮的定义详见《程序编写规则》)。
这几乎占据了 90%的编写服务器代码的时间。
当我们写好了功能,要想的是,如果一旦出现了某些极端情况会怎样。而不要想,反
正出现了极端情况也是以两年以后的事情了。这是我们服务器程序与客户端程序最大的不
同。
我们写程序不能留尾巴。要做到完成一段,就让这段代码完全的 Bug Free。不用过几
个月,甚至过几年还要回过头来看这些代码。否则我们就永远被这些代码拴住,而无法进
步了。
对 BUG 的监测
那么如何加强对如此复杂的程序的监控呢?下面有一些方法。这些方法对于单机程序
而言,可能并不重要,但是对于网络程序而言,就显得比较重要了。这个时候我们写代码
其主要作用就不仅仅是实现游戏的功能,更重要的是如何使我们的代码错误更少,出了错
之后更容易被找到。
注:因为网络游戏的特殊性,我们必须不断地更新游戏,所以游戏基本上不可能出现
一个阶段,在这个阶段里是完全 BUG Free 的。很多修改都要求我们在没有完全进行测试的
情况下就必须上线,实际上进行所谓的完全测试也基本上是不可能的。所以,这要求我们
必须很快的定位错误,并且在错误一开始发生的时候就尽量的收到报警并找到它。
Assert
在每一个模块,线程,函数的参数输入部分,增加 Assert()进行参数合法性判定。但是
要注意,这个函数的作用仅仅限于 Debug 版,对于查找那些非常隐蔽的错误用处是不大的。
所以一般仅仅在程序开发的前期使用。到了后期,基本上要以后后面的解决办法来查找问
题。
assert( strlen(szMsg) < sizeof(szMsg) );
注:在天骄 II 的时候,因为 ASSERT 的作用实在是太大了,我们又增加了一个编译选
项: Final 版。也就 是 说 除了普通的 Debug 和 Release 编译 选 项 以 外 , 又 增 加 了 一 个
Final 。 Final 才 是 最 终 服 务 器 会 用 到 的 版 本 。 而 我 们 在 Release 版 里 , 重 新 定 义 了
ASSERT(),而不是原来的简单的把代码设置为 NULL。重新定义以后,ASSERT()就不再报
对话框,而是直接写 log 文件,这在公测期间尤为重要。可以随时帮助我们防范错误。
Log 文件
因为游戏的服务器经常需要长时间运行,而且大多是 Release 版的情况下,所以非常有
必要对那些出现错误的地方进行随时的记录。对错误的输入要有记录。主要需要记录的内
容有:
正常错误。程序中可能出现的正常错误,比如资源没有找到,读写磁盘失败,登
陆失败等等。
非正常错误。不应该出现的错误,比如人物没有找到,道具属性没有找到,怀疑
是作弊的行为等等。
对于网络程序,几乎要在任何我们认为可能出现错误的地方写下 Log 记录。但是因为
Log 记录的操作非常消耗时间,所以对于那些调用非常频繁的地方不适合用 Log 来记录,
那就需要下面的方法。
2
WriteLogFile( "easyrpg.log", "Here cannot be a room!\n" );
注:因为 log 比较慢,所以在天骄 I 的后期,和天骄 II,我们将这些信息输出给另外一
个线程,后者是另外一台计算机,然后再保存。这里的用途除了查找 BUG 以外,另外一个
主要的用途是记录玩家的操作,这是为了追查复制等玩家作弊行为,监控游戏的公平性,
防止玩家刷钱,洗钱。
Try 和 Catch
网络服务器程序经常需要运行较长的时间,而且一旦出现错误,无法得知到底是在哪
里出现的。Try 和 catch 就帮助我们解决这个问题。Try 的作用就是保证如果这部分代码出
现的了异常,程序会自动返回到一个 catch 中的指令里继续执行。而不会出现非法指令的问
题。
我们的全部代码都应该被保护在 try 和 catch 里,层层嵌套。在现实情况下,错误往往
会出现在程序的任何一个地方,可能会在任何时候出现,而且这些错误往往是不能立刻再
现的。我们的程序员已经不可能针对每一个错误长时间的进行“再现”尝试和跟踪。这时候
往往需要我们一边用 try 先把错误跳过去,让程序可以继续运行,另一方面缩小包围圈,逐
步找到问题的真正所在。
Try 和 catch 的最大作用是当程序发生了错误,我就可以立刻知道在哪个范围里,哪个
函数里发生了错误。虽然发生错误的地方和产生错误的地方可能并不一定是一个地方,但
是至少可以帮助我们尽快的确定到底是哪里出了错,并且不让这里继续出错。
在天骄里经常可以遇到几个月以后才最终找到 BUG 的情况。往往当一个错误发生了,
我们并不能很快定位出错的原因。但是如果我们的程序内部有这样一个由 log 和 try 这样的
纠错机制所组成的“网”的话,会非常有助于我们尽快解决问题。
实际上一般,try 和写 log 都在一起使用,一旦发生了异常,被 catch 住,就应该写 log
把相关的信息打印出来。
int aaa = 0;
#ifndef _DEBUG
try
{
#endif
…(实际的代码 1)
aaa = 1;
…(实际的代码 2)
aaa = 2;
…(实际的代码 3)
aaa = 3;
…
#ifndef _DEBUG
}
catch(...)
{
char szMsg[ER_MESSAGE_SIZE];
sprintf( szMsg, "newpersonex() Error : %d <%s %d %d>\n", aaa, szType, nLevel, nSLevel );
WriteLogFile( "easyrpg.log", szMsg );
}
#endif
这里要说明一下,变量 aaa 的作用就是帮助我们定位到底是在执行哪段代码,哪个函
数的时候发生了异常。以便于我们下次在该函数内部写入这样的 try 和 catch 的代码,继续
跟踪。
注意:对于还没有发布的程序,尤其是单机版游戏,草率的使用 try 反而是有害的(假
如 try 不能很快定位错误的话)。因为这样会徒然导致许多很奇怪的错误的产生,会掩盖真
正出现错误的地方。
注:Try 和 Catch 不能滥用,这里再次强调,尤其在客户端程序,我们不建议使用。甚
至我们在天骄 II 里,基本上很少使用 Try 和 Catch 了。一个主要原因是,因为吸取了天骄 I
的经验,所以天骄 II 崩溃的机会比天骄 I 要少了很多。我们基本上没有必要随时保证服务
器的稳定运行。另外一个主要原因是我们找到了一个更好的办法。
3
剩余11页未读,继续阅读
资源评论
- u0111914822013-08-15虽然很短,但都是作者的经验之谈,很受用
- hkd_test_0012014-07-15很实用,谢谢分享
- cidofzion52013-01-09虽然很短但是写得还可以
- CanBeABM2012-05-30仔细看了一下,里面许多技巧都很实用,虽然有些现在已经算是默认的准则,但能在03年在项目中自己摸索着总结出来,说明作者还是很有水平的(估计是核心开发人员)。里面的几段代码风格感觉不错,像strcpy_ss,不过觉得很碍眼的是实现类名都加了前缀C,看起来特别别扭(匈牙利命名法有的前缀加上去就很美观,有的像大便)。 作者乐意拿出来分享,还是很谢谢作者的。 顺带看了一下,现在天骄3都实现了无缝地图技术,应该也是挺好玩的
footman136
- 粉丝: 0
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功