智勇三国工作概要
使用文件而不是数据库
使用文件比使用数据库可以大幅减少工作量。为了方便服务端和客户端通信,几乎每个类有都有读写函数:
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造假的金钱成本或时间成本很高,往往得不偿失。三,输入验正码。可以防止大中付费玩家,但防止不了大中时间玩家。而且有一个严重缺点:验正码会让玩家不舒服。
荣耀
史玉柱:“在《征途》里,一旦有本国的镖车被劫,那些大号会奋不顾身地去保护那些小号,去救镖。为什么会去救镖?大号需要自己花钱买竹蜻蜓,救好之后在利益上对自己也没有任何好处。你分析他的心理,其实他就是为了满足他的荣耀,被救的人的一声谢谢就让他很高兴。如果遇到一个识相的小号再刷一下屏,说:“谢谢××救了我的镖。”他又会开心十分钟。所以到游戏里,不管大号小号,玩家内心最渴望得到的就是荣耀。”我的理解是给大玩家创造一个无偿帮小玩家的机会。于是出了重楼任务,任何人都可以完成自己或别人的任务,但任务完成者没奖励,只有接任务者有奖励。效果很好。
惊喜
惊喜其实就是随机性。我以前是做应用软件的,而且不想挨骂,所以尽可能地抹杀随机性。于是游戏平淡无奇,直到最近才重视惊喜,重头戏就是彩票,和现实类似,用游戏中的钱抽奖,中了得大量游戏中的钱。结果玩家反应这是赌博,不是惊喜,因为抽奖是要成本的。于是改成抽奖用“彩票”,中了得大量游戏中的钱。“彩票”的获得不影响正常打怪,所以可以理解成不需要成本。效果观测中。
防野指针
服务端崩溃基本是由野指针引起的,而且基本上是CYongHu和CRenWu两个类的野指针引起的。让这两个类派生于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));
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~