《征途》服务端源码解析:进程架构、启动顺序与数据库初始化实战

发布时间:2026/10/17 4:56:58
《征途》服务端源码解析:进程架构、启动顺序与数据库初始化实战
简介《征途》服务端与客户端整套源码包面向具备一定 C/C 基础的游戏研发人员与网络游戏研究者旨在帮助其深入理解大型 MMORPG 从通信协议到业务逻辑的完整实现包内涵盖服务端核心程序、客户端图形界面与渲染代码、数据库建表与初始化脚本以及源码结构说明、编译指南和依赖配置等辅助文档适合用于引擎改造、服务器性能优化或客户端技术学习。压缩包共 2000 个文件大小约 133.39MB文件类型以 h/cpp/hpp/c 等源代码文件为主同时包含大量 xml、properties 配置、lua 脚本、sql 数据库脚本以及 makefile、vcproj/sln 等工程构建文件可较完整地还原项目编译环境。已有 2938 人学习下载通过源码可观察服务端任务调度、网络同步、负载均衡等机制研究客户端渲染、动画与 AI 模块数据库部分则展示玩家数据、道具与进度的高效存储与查询策略。说明文档能帮助快速搭建编译环境并定位关键模块减少前期探索成本适合作为游戏服务器开发与大型项目代码阅读的实战样本。1. 这套《征途》源码包到底是什么先弄清楚再下载在资源站看到《征途》服务端源码客户端源码数据库这种打包老开发和新手反应完全不一样。老开发知道这不是一键架设包而是一套当年真实网游留下来的C工程服务端按进程拆职责客户端是Win32/MFC工程数据库给的是MySQL初始化脚本三部分各就各位。它真正能解决两件事一是让你从零把服务端跑通看到登录界面再进到游戏二是给你一份研究大型MMORPG服务端架构的活教材登录、网关、地图、DB代理一环扣一环。适合想搞懂网游服务端进程模型的人也适合拿来做课程设计、毕业设计参考。要是一心想开服盈利那不是这篇文章的方向。2. 服务端架构登录、网关、地图、逻辑四个进程的启动顺序与配置2.1 先从bin目录认起每个exe负责什么解压后别急着找工程文件双击先把服务端bin目录下的exe认一遍。经典的两代MMORPG服务端都是按进程拆职责这套核心进程一般是这几个登录服负责账号验证和下发服务器列表网关服负责接管客户端长连接并转发数据包地图服承载场景、移动、碰撞和怪物AI逻辑服处理技能、任务、掉落这些数值向的东西日志服集中写日志DB代理服是业务进程访问数据库的中间层。之所以不把所有逻辑塞进一个exe一方面是为了压榨多核CPU另一方面也是当年横向扩服的必经之路——一组进程就是一个区再加一组就是新区。新手最常犯的错是把这几个进程当成一个整体全部启动结果某个进程起不来导致连锁崩溃。我一般建议先启动数据库和日志服再启动登录服确认登录服起来后再拉网关最后是地图和逻辑。判断进程是否真的起来了不要只看任务管理器里有没有进程名要看它自己的日志文件多数进程启动失败时会往日志里写致命错误这个习惯能帮你省下大量排查时间。2.2 编译环境老代码挑编译器别一上来追最新版源码工程文件如果是老版本Visual Studio的格式新版本打开时会有一次转换提示转换后报错一大片是常态。这套代码当年基本按32位编译用64位默认配置去编会死在链接阶段。常见做法是先把平台工具集固定到v100或v90能跑通就不要去动字符集设置——老服务端的代码里大量用多字节编码写死了字符串改成Unicode会引发连锁错误。我自己在搭这类老源码时不会一上来就编译主程序而是先单独编译一个依赖最少的小工程比如日志库或公共库验证编译链路没问题再编主体全量编译首次可能要跑十几分钟这期间最好不要动机器老工程最怕编译到一半被杀掉再来一次时各种中间文件残留错误信息会变得更不可读。2.3 三张核心配置IP、端口和数据库连接串服务端每个进程几乎都有自己的一份配置文件但骨架是一样的。先看数据库连接[Database] Host127.0.0.1 Port3306 Userroot Password123456 DbNameztgameHost是数据库服务器地址Port是MySQL端口DbName是库名。注意老代码里密码是明文存放的别因为嫌不安全就换掉它很多进程只认配置文件里的明文密码改了之后得同步改多个文件容易漏一个导致某进程连不上库。网络配置一般长这样[Network] LoginPort9901 GatePort9902 MapPort9903 LogicPort9904每个进程监听自己的端口客户端先往登录端口发连接请求登录验证通过后再按服务器返回的地址去连网关端口。这里改端口之前要确认没被系统占用常见排查命令是用netstat -ano | findstr 9901看一下占用进程如果被占用服务端启动日志里也会有端口绑定失败的记录。2.4 启动顺序为什么必须先登录服再开网关网关服在启动时通常要去登录服注册自己告诉登录服“我这边在线、可以分配玩家过来”。如果登录服还没起来网关会反复重试并写连接失败日志反过来先开网关再开登录服登录服可能接受了注册但网关已经处于半死状态玩家拿不到服务器列表表现就是客户端能打开但永远在“获取服务器列表”转圈。我一般用这样一个顺序脚本来做日常启动每次手工起服都按它走# Windows下依次启动间隔给足 start mysql start LogServer.exe timeout /t 3 start LoginServer.exe timeout /t 3 start GateServer.exe timeout /t 3 start MapServer.exe start LogicServer.exetimeout参数单位是秒给3秒是让上一个进程完成绑定端口和连接数据库的动作。如果你的机器比较慢把timeout调到5秒。启动完之后逐个打开bin/log目录下的进程日志确认每一行末尾没有ERROR级别记录再进下一步这一步比看进程列表可靠得多。3. 客户端编译与连服改四个配置点让账号进得去3.1 客户端源码目录主程序、界面层和游戏逻辑的边界客户端工程解压后目录层次比服务端还深但核心无非三块主程序负责Win32窗口、消息循环和网络收发界面层是一堆跟UI相关的类游戏逻辑管场景渲染、角色控制、技能表现。老MMO客户端还有一个特殊目录叫资源目录里面是美术配置和地图配置编译时通常只编代码运行时从打包好的资源目录加载资源资源和代码的版本号必须严格对应。我在本地搭这套东西时客户端源码实际上只需要保证能编译出一个exe画面资源都走现有资源目录。如果某次改了客户端代码重新编译要注意客户端与服务器交互的数据包格式是写死协议号的只要动协议定义就必须同时更新服务端对应文件否则客户端能过登录但会卡在读条这算老源码最经典的联动问题。3.2 编译客户端的环境Win32、多字节、先过资源配置文件客户端工程比服务端更容易踩字符集的坑因为它有大量面向玩家的中文文本。老客户端工程默认是多字节字符集我用VS2010打开工程后做的第一件事是确认三处平台工具集、字符集、目标平台是Win32还是x64。老代码切x64多数会死在资源编译上不值得折腾老老实实编32位。下面这个预编译宏常见于老客户端工程配置里// 老客户端工程里常见两种宏开关二选一 // #define UNICODE // 这行要注释掉否则中文界面全乱码 #define _MBCS // 启用多字节字符集老代码默认路径如果你看到源码里带TCHAR说明作者当初给双字符集都留了余地但实际测试时重点还是走多字节路径。改完字符集后最好先编译一个最小的对话框工程确认编译链路通再编整个客户端否则几千个文件编到一半才报错排查成本很高。3.3 改服务器列表客户端指向本机的四个位置客户端连哪个服务器通常不是代码里写死而是来自配置。老一代客户端一般有独立配置文件常见命名是serverlist.ini、config.ini格式大致是[ServerList] Count1 Server1Name本地测试 Server1IP127.0.0.1 Server1Port9901Server1IP填服务端登录服的地址Server1Port填登录端口。这里说的四个位置是指服务器列表文件、客户端逻辑层读列表的代码路径、版本校验文件里的服务器类型标识、以及资源路径下的同名配置。只改其中一个最常见的表现是客户端公告能刷出来但点登录按钮没反应。改完配置后把客户端的本地缓存清一遍。老客户端会在本机生成一个cache目录保存服务器列表快照不清缓存的话你改的IP会被缓存覆盖表现为无论怎么改都连不上清理后重启客户端才生效。这个坑我踩过不止一次后来基本养成习惯改配置必清缓存清缓存必重启客户端。3.4 版本号与一致性客户端、服务端、资源包三者必须对齐大多数老MMO在这块都是同一个套路客户端启动时把自己的版本号发过去服务器比对后决定是否允许登录。版本号常定义在头文件里比如// Version.h 中定义版本号改了要同步服务端配置 #define VERSION_MAJOR 1 #define VERSION_MINOR 0 #define VERSION_BUILD 1001服务端在配置文件里会写一个期望版本号我一般把服务端期望值和客户端头文件里的值设成相同再编译避免一半机器能登一半不能登。如果改了客户端代码建议把VERSION_BUILD加一这样能在日志里直观看到新版本是否被服务器接受。版本不一致的经典报错是“客户端版本过低”或者客户端读完进度条后直接被踢回登录界面。此时最快定位手段不是翻代码是去服务端日志里看接收到的版本号日志里一般会有一行client version x.x对照一下就知道是哪一侧没对上。4. 数据库初始化账号、角色、物品的数据链路是这样串起来的4.1 数据库选型为什么老源码多数跟着MySQL 5.x走这套包里的SQL脚本是面向MySQL的老项目一般用5.x版本比较多因为当时InnoDB还在普及过程中而且老代码大量依赖MyISAM的快读特性。如果直接装最新版MySQL执行脚本时大概率会遇到两类问题语法不兼容和默认字符集不匹配。我的建议是搭一个5.7版本环境一方面与老脚本兼容性好二方面这个版本是目前身边最容易找到稳定包的环境。建库脚本开头通常是这样的CREATE DATABASE IF NOT EXISTS ztgame DEFAULT CHARACTER SET gbk; USE ztgame;这里库名要跟服务端所有进程配置文件里的DbName一致大小写都要一致。老代码在Windows下对库名大小写不敏感但如果你把库迁到Linux上托管库名大小写错一个字母就直接连不上所以从一开始就统一用小写最省事。4.2 全库初始化核心表和它们之间的血缘关系执行完建库脚本后库里会出现一批业务表新手常被一堆表名劝退但核心链路其实很清晰。登录阶段只碰账号表角色表负责角色列表的读写账号和角色靠account_id关联角色和物品靠role_id关联。手写一个最小示例方便理解这层关系CREATE TABLE account ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(32) NOT NULL, password VARCHAR(64) NOT NULL, gm_level TINYINT NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETgbk; CREATE TABLE role ( id INT NOT NULL AUTO_INCREMENT, account_id INT NOT NULL, name VARCHAR(32) NOT NULL, level INT NOT NULL DEFAULT 1, exp BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_account (account_id) ) ENGINEInnoDB DEFAULT CHARSETgbk;account表的gm_level字段是后面调GM命令的开关默认0是普通玩家置成1可以用GM指令。role表的account_id指向account.id角色归属就在这一列。真实库的命名风格未必完全一致但只要看到这层关联整个数据模型就串起来了后面查问题也不会被一堆附属表带偏。4.3 新账号从哪里来注册流程在服务端哪一段很多人在数据库里手工INSERT一条账号后发现客户端登录时提示“密码错误”原因多半是密码字段在代码里不是明文存储而是做了摘要处理。服务端的注册逻辑一般放在登录进程中注册时对密码做一次摘要再写库登录时把输入做同样处理再比库。手工插数据如果不走注册流程密码字段的格式就对不上。先手工插一条调试账号可以走服务端注册接口也可以在库里直插。直插时注意密码字段格式参考脚本里已有数据的写法。我一般这样给测试账号开GMINSERT INTO account (username,password,gm_level) VALUES (test,这里填与服务端摘要算法匹配的密文, 1);这段SQL里的password值必须跟服务端摘要结果匹配否则表现为能登录但进游戏后角色列表为空。如果你不确定摘要算法最稳的办法是先用游戏里的注册功能建一个号然后去库里把gm_level改成1绕开手工算摘要的麻烦。这个绕法做测试非常省心建号、开GM、进游戏三步走完。4.4 数据链路验证从建号到进游戏数据库里发生了什么当你从一个干净数据库开始最后进游戏数据库里应该留下三条痕迹account表多一行账号role表多一行角色物品相关的表出现初始装备记录。如果只到登录界面就断开检查account表有没有新增记录如果登录成功但创建角色失败去role表看是不是已经有同名角色老代码对重名的校验经常是直接查库同名会卡死在创建界面。一次性把这几张表导出来对比基本能定位一大半数据侧的问题。我习惯的做法是进入游戏后先在库里执行这条语句确认角色数据落库SELECT id, account_id, name, level, exp FROM role WHERE account_id 1;看到角色等级和经验再去看物品表确认初始物品已写入。链路全通说明数据库侧没有暗坑后面再去调服务端的玩法配置就不会被误导。相反如果这条SQL查出来是空行说明角色数据根本没写进去问题一定在服务端逻辑或权限层而不是客户端。5. 避坑指南架《征途》服务端最容易翻车的五个现场5.1 现象客户端提示“连接服务器失败”日志里没有明显ERROR原因IP和端口配置存在于多个位置你改的那一处和进程实际读取的位置不是同一个。老服务端的配置读取路径经常用相对路径加固定文件名如果工作目录不对进程会读取到默认值客户端自然连不到预期地址。 解决先在任务管理器里确认进程的工作路径再看它加载的配置文件路径不要只看bin目录下那份。我一般会在各配置里临时加一个标识行重启后查日志输出确认哪份配置文件被真正读取反复几次后把客户端、登录服、网关注册三处的IP填成同一个127.0.0.1问题基本消失。5.2 现象服务端能启动但日志里一堆DB connect failed或乱码原因常见有两个一是MySQL用户名密码不对二是字符集不匹配。老脚本用GBK建库新版MySQL默认utf8mb4连接管理器按GBK解释读出来就是乱码。乱码的表在执行初始化脚本时就已经出现进程读配置时再按错误字符集拼接SQL整条链路都是乱的。 解决建库时显式指定GBK或者把MySQL的character_set_server设为gbk不要依赖默认值。连接字符串里如果支持charset参数就加上charsetgbk服务端进程里的数据库连接参数多半在配置文件或公共代码里把编码锁死后再重启所有进程。改完后去数据库里查一条中文装备名显示正常再往下走。5.3 现象服务端内存持续上涨两小时后玩家掉线原因老服务端的内存池和定时清理逻辑依赖日志服按时归集数据如果日志服没启动或端口被占业务进程会把待写日志积压在自己内存里越积越多。不少新手只拉登录、网关、地图三个进程把日志服漏掉前几个小时表现正常后续就是雪崩式掉线。 解决把日志服也纳入启动顺序日志目录要有写权限。日志服起来后观察它的日志滚动是否正常如果某个进程的日志文件长时间不增长说明日志链路已经断了。内存上涨时先看任务管理器里哪个进程异常再启动对应日志进程等内存回落后再继续测试。这个坑最隐蔽因为症状和内存泄漏一模一样实际只是日志没落地。5.4 现象客户端过完登录读完进度条直接白屏或被踢回原因客户端版本号和服务端期望版本号不一致多数发生在你改了客户端代码重新编译却忘了同步服务端配置。版本校验在登录和读条两个阶段各做一次第一次没拦住第二次也会拦。 解决把服务端期望版本号改成跟客户端头文件一致重新启动服务端。如果日志里能看到客户端上报的版本号就以日志里的数字为准。另外客户端本地也有版本缓存改完版本号后不清缓存直接启动等于没改。这个现场我见过太多次清缓存这个动作一定要写进自己的操作清单里。5.5 现象源码编译到一半报错死在预编译头或资源脚本原因老工程用VC的预编译头机制工具链升级后对预编译头的路径校验更严格中间文件残留也会导致编译无法继续。资源脚本文件里的字符集声明与工程不一致时资源编译器直接报错。 解决先设置平台工具集和字符集再清理解决方案删掉Debug/Release目录下的中间产物最后重新生成。rc文件报错时检查文件头部的编码声明和工程字符集是否一致。编译顺序上先编译公共库工程再编主程序不要一上来就全量这样能把大部分错误挡在最小范围内定位也快。6. 进阶调优用GM命令把空服调成可测试的状态6.1 先验证一条链GM命令是否生效把数据库account表的gm_level改成1后重启服务端用该账号进游戏在聊天框里输入GM命令。如果聊天框没反应注意命令是否需要指定频道老代码里GM命令只在特定频道生效切到GM频道再试一次。输入后看一眼服务端日志正常会打一条GM command recv之类的记录。命令没生效时九成是gm_level没生效或者服务端读取的是角色表字段而不是账号表字段回库里确认后重新登录。6.2 经验倍率和掉率不用改代码改配置表调优最常动的是经验倍率和物品掉率服务端有一张配置表或配置文件里面的expRate和dropRate就是全局倍率。把expRate改成10打一只怪的经验就是原来的10倍UPDATE server_config SET expRate 10, dropRate 5 WHERE id 1;这种更新只影响新产生的掉落和怪物死亡时的经验分配已刷在身上的怪不受影响。不想动数据库的话也可以直接在服务端配置文件中找到ExpRate字段改数值改完重启逻辑服生效不影响其他进程。最后说一个我自己的教训一开始我图省事把配置文件、数据库倍率、GM权限一次性全改到位结果出问题时根本不知道是哪一步引起的。之后我每次只改一个点改完走一遍完整链路——登录、建角色、打怪掉经验、查库确认后再改下一个。这套源码本身不复杂复杂的是被多个进程、多份配置分散开的耦合点一步一步验证是最省时间的。希望帮到你。本文还有配套的精品资源点击获取