智勇三国工作概要

来源:互联网 发布:淘宝奥比岛珠宝表情 编辑:程序博客网 时间:2024/06/02 17:39

智勇三国工作概要

使用文件而不是数据库

使用文件比使用数据库可以大幅减少工作量。为了方便服务端和客户端通信,几乎每个类有都有读写函数:

    void WriteToBuf( CFile& file ) const ;

int ReadFromBuf(const BYTE* buf,int iPos,int iLen ) ;

有了这两个函数,各个类的对像存取文件非常方便。使用文件系统相比使用数据库系统,也会少量增加工作量,比如:(1),写文件的时候,物理服务器刚好当了。(2),快速存取部分文件。(3)性能。这些东西工作量不大,且是一次性的,封装成函数后,以后都可以直接调用。所以,选取了直接使用文件,而不是数据库系统。

防攻击

1,服务端给每个用户只留50k的通信缓存。

2,限制每个用户给服务端发送信息的次数。初始10次,每0.4秒增加一次。客户端每10秒给服务端发一次心跳包,无论用户的手速多快,正常操作都不会快于0.4秒,所以不会影响正常操作。

3,发现用户数据格式不对后,马上断开连接。

事实证明,这个是多余的。因为别人直接攻击操作系统比攻击我的服务端更容易。有一次服务器被攻击得断网,空间商处理后,我按网上查到的方法对服务器进行防攻击配置,效果很明显,再遭到攻击,服务器没断网,只是变卡,而且不超过一小时就会自动正常。

 

多线程

最初方案是每登陆一个用户开启一个线程,大约在10处用CEvent进行同步。试运行了一段时间,发现每隔几天数据就混乱一次,受尽折磨后,发现是一个同步那有小问题。痛定思痛后,简化成两个线程。服务线程处理所有逻辑,主线程只处理后台输入、输出和客户端通信。主线程将要处理的数据放到缓存,服务线程和主线程的交互只限此缓存,所以处理起来简单得多。事实证明,此方案相对完美地解决了多线程的问题。由于是回合类文字型游戏,所以对实时性要求很低,服务线程每0.2秒读一次缓存。

 

内存泄漏

内存泄漏出现过几次,但很快都被发现并解决。因为无论是服务端还是客户端,都只占用了约20M内存,一有内存泄漏,就可以很明显感到。

 

句柄泄漏

有玩家反应,开三五个号挂一两天,就会很慢很慢。经反复分析发现是:LoadImage后忘记DeleteObject。事后诸葛亮:“其实可以通过工具(ProcessExplorer)查看句柄泄漏”。

 

服务端无响应与崩溃

这两个问题很头痛,但好在不损坏数据,所以有一个治标不治本的方法。开一个监视程序(Watch.exe),发现服务端(Server.exe)当了,就重启。流程如下:一,服务端每0.2秒在内存映射文件(OpenFileMapping)打一个标。二,监视程序每10秒查看一次内存映射文件。三,如果发现服务端60秒内,没打标,则认为服务端已经当了。杀掉server.exe进程,并重启server.exe。治本很难,奋斗两年多,也没根治,只是大幅减少当机的频率。先是利用map文件查当机,发现这个方法有四个问题:一,无法查服务端无响应,如:死循环,弹出模式对话框。二,不直观。三,map文件和exe必须一致,而实际情况是很容易不一致。四,每次更新都必须备份map文件。改进方法是:在服务端的关键函数入口在内存映射文件上打标。监视程序发现服务端当了后,将打的标,复制到sysinfo.txt中。

 

数据存储

效率如此重要,怎么能交给系统呢,于是我没用数据库,直接用的自定义文件。对服务端而言,数据存储占用了绝大部分CPU。数据存储最占CPU的地方有两处:一,人物信息,占了总数据量的90%。二,玩家信息,每次存储都要加密。对人物信息,每次只重新存储需要保存的人物,因为绝大部分人物都是不在线的,所以这样可以大大提高效率。对玩家信息,只在玩家信息被修改的时候存储。由于平均一天只有约20多个用户注册,所以玩家信息很少被存储。其它文件都是0.2秒存储一次。

 

数据被恶意修改

服务端数据被恶意修改,发生过一次,影响很恶劣。查了一下午加一晚上,都没发现问题所在。第二天一觉醒来,突然发现一个“深思熟虑”的想法,原来是:人物在某种情况下保存会失败。卖出的时候,让交易信息保存成功,人物信息保存失败就可以刷东西了。

 

防小号

游戏中防止贫富差距过大,可以大幅减少流失。扶植弱势群体的难点在于区分弱势各群体和大玩家的小号。主要思路有两个:一,扶植的东西,不能交易,且获取需要一定的时间。大玩家不屑于把时间花在小号上。二,根据IP判断。IP造假的金钱成本或时间成本很高,往往得不偿失。三,输入验正码。可以防止大中付费玩家,但防止不了大中时间玩家。而且有一个严重缺点:验正码会让玩家不舒服。

 

荣耀

史玉柱:“在《征途》里,一旦有本国的镖车被劫,那些大号会奋不顾身地去保护那些小号,去救镖。为什么会去救镖?大号需要自己花钱买竹蜻蜓,救好之后在利益上对自己也没有任何好处。你分析他的心理,其实他就是为了满足他的荣耀,被救的人的一声谢谢就让他很高兴。如果遇到一个识相的小号再刷一下屏,说:“谢谢××救了我的镖。”他又会开心十分钟。所以到游戏里,不管大号小号,玩家内心最渴望得到的就是荣耀。”我的理解是给大玩家创造一个无偿帮小玩家的机会。于是出了重楼任务,任何人都可以完成自己或别人的任务,但任务完成者没奖励,只有接任务者有奖励。效果很好。

 

惊喜

惊喜其实就是随机性。我以前是做应用软件的,而且不想挨骂,所以尽可能地抹杀随机性。于是游戏平淡无奇,直到最近才重视惊喜,重头戏就是彩票,和现实类似,用游戏中的钱抽奖,中了得大量游戏中的钱。结果玩家反应这是赌博,不是惊喜,因为抽奖是要成本的。于是改成抽奖用“彩票”,中了得大量游戏中的钱。“彩票”的获得不影响正常打怪,所以可以理解成不需要成本。效果观测中。

 

防野指针

服务端崩溃基本是由野指针引起的,而且基本上是CYongHuCRenWu两个类的野指针引起的。让这两个类派生于CFangYeZhiZhen就是了,此类关键代码如下。构造函数调用之后,析构函数调用之前,m_iZhiZhenFlag的值一定是0Xabcdef12,如果不是此值,则很可能是野指针。

CFangYeZhiZhen::CFangYeZhiZhen()

{

m_iZhiZhenFlag =0Xabcdef12;

}

 

CFangYeZhiZhen::~CFangYeZhiZhen()

{

m_iZhiZhenFlag = 0 ;

}

 

 

void CFangYeZhiZhen::CheckYeZhiZhen(CString strFlag) const

{

if( 0Xabcdef12 != m_iZhiZhenFlag)

{

ASSERT(false);

throw( new CMyException("野指针"+strFlag));

}

}

 

                                                                         

1 0
原创粉丝点击