没有合适的资源?快使用搜索试试~ 我知道了~
mangos服务器架构.pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 178 浏览量
2021-10-02
11:59:59
上传
评论
收藏 26KB PDF 举报
温馨提示
试读
11页
mangos服务器架构.pdf
资源推荐
资源详情
资源评论
登录服的设计 -- 功能需求
正如我们在前面曾讨论过的, 登录服要实现的功能相当简单, 就是帐号验证。 为了便于描述,
我们暂不引入那些讨论过的优化手段, 先以最简单的方式实现, 另外也将基本以 mangos的代
码作为参考来进行描述。
想象一下帐号验证的实现方法,最容易的那就是把用户输入的明文用帐号和密码直接发给登
录服,服务器根据帐号从数据库中取出密码,与用户输入的密码相比较。
这个方法存在的安全隐患实在太大,明文的密码传输太容易被截获了。那我们试着在传输之
前先加一下密, 为了服务器能进行密码比较, 我们应该采用一个可逆的 加密算法, 在服务器
端把这个加密后的字串还原为原始的明文密码,然后与数据库密码进行比较。既然是一个可
逆的过程,那外挂制作者总有办法知道我们的加密过 程,所以,这个方法仍不够安全。
哦,如果我们只是希望密码不可能被还原出来,那还不容易吗,使用一个不可逆的散列算法
就行了。 用户在 登录时发送给服务器的是明文的帐号和经散列后的不可逆密码串, 服务器取
出密码后也用同样的算法进行散列后再进行比较。 比如,我们就用使用最广泛的 md5算 法吧。
噢,不要管那个王小云的什么论文, 如果我真有那么好的运气, 早中 500w了,还用在这考虑
该死的服务器设计吗?
似乎是一个很完美的方案,外挂制作者再也偷不到我们的密码了。慢着,外挂偷密码的目的
是什么?是为了能用我们的帐号进游戏!如果我们总是用一种固定的算法来对密码做散列,
那外挂只需要记住这个散列后的字串就行了,用这个做密码就可以成功登录。
嗯,这个问题好解决,我们不要用固定的算法进行散列就是了。只是,问题在于服务器与客
户端采用的散列算法得出的字串必须是相同的,或者是可验证其是否匹 配的。很幸运的是,
伟大的数学字们早就为我们准备好了很多优秀的这类算法,而且经理论和实践都证明他们也
确实是足够安全的。
这其中之 一是一个叫做 SRP的算法,全称叫做 Secure Remote Password,即安全远程密码。
wow使用的是第 6 版,也就是 SRP6算法。有关其中的数学证明,如果有人能向我解释清楚,
并能让我真正弄明白的话, 我将非常感激。不过其代码实现步骤倒是并不复杂, mangos 中
的代码也还算清晰,我们也不再赘述。
登录服除了帐号验证外还得提供另 一项功能,就是在玩家的帐号验证成功后返回给他一个服
务器列表让他去选择。这个列表的状态要定时刷新,可能有新的游戏世界开放了,也可能有
些游戏世界非常 不幸地停止运转了, 这些状态的变化都要尽可能及时地让玩家知道。 不管发
生了什么事, 用户都有权利知道, 特别是对于付过费的用户来说, 我们不该藏着掖着, 不 是
吗?
这个游戏世界列表的功能将由大区服来提供,具体的结构我们在之前也描述过,这里暂不做
讨论。登录服将从大区服上获取到的游戏世界列表发给已验证通过的客户端即可。好了,登
录服要实现的功能就这些,很简单,是吧。
确实是太简单了,不过简单的结构正好更适合我们来看一看游戏服务器内部的模块结构,以
及一些服务器共有组件的实现方法。这就留作下一篇吧。
服务器公共组件实现 -- mangos 的游戏主循环
当阅读一项工程的源码时, 我们大概会选择从 main 函数开始, 而当开始一项新的工程时, 第
一个写下的函数大多也是 main。那我们就先来看看, 游戏服务器代码实现中, main 函数都做
了些什么。
由于我在读技术文章时最不喜看到的就是大段大段的代码, 特别是那些直接 Ctrl+C 再 Ctrl+V
后未做任何修改的代码, 用句时髦的话说, 一点技术含量 都没有! 所以在我们今后所要讨论
的内容中,尽量会避免出现直接的代码,在有些地方确实需要代码来表述时,也将会选择使
用伪码。
先从 mangos 的登录服代码开始。 mangos 的登录服是一个单线程的结构,虽然在数据库连接
中可以开启一个独立的线程,但这个线程也只是对无返回结果的执行类 SQL做缓冲,而对需
要有返回结果的查询类 SQL还是在主逻辑线程中阻塞调用的。
登录服中唯一的这一个线程,也就是主循环线程对监听的 socket 做 select 操作,为每个连
接进来的客户端读取其上的数据并立即进行处理, 直到服务器收到 SIGABRT或 SIGBREAK信号
时结束。
所以, mangos登录服主循环的逻辑,也包括后面游戏服的逻辑,主循环的关键代码其实是在
SocketHandler 中,也就是那个 Select 函数 中。检查所有的连接,对新到来的连接调用
OnAccept 方法, 有数据到来的连接则调用 OnRead方法, 然后 socket 处理器自己定义对接收
到的数据 如何处理。
很简单的结构,也比较容易理解。
只是,在对性能要求比较高的服务器上, select 一般不会 是最好的选择。如果我们使用
windows 平台,那 IOCP将是首选;如果是 linux , epool 将是不二选择。我们也不打算讨论
基于 IOCP 或是基于 epool 的服务器实现,如果仅仅只是要实现服务器功能,很简单的几个
API 调用即可,而且网上已有很多好的教程;如果是要做一个成熟的网络服务器产品, 不是
我几篇简单的技术介绍文章所能达到。
另外,在服务器实现上,网络 IO 与逻辑处理一般会放在不同的线程中,以免耗时较长的 IO
过程阻塞住了需要立即反应的游戏逻辑。
数据库的处理也类似,会使用异步的方式,也是避免耗时的查询过程将游戏服务器主循环阻
塞住。想象一下,因某个玩家上线而发起的一次数据库查询操作导致服务器内所有在线玩家
都卡住不动将是多么恐怖的一件事!
另外还有一些如事件、脚本、消息队列、状态机、日志和异常处理等公共组件,我们也会在
接下来的时间里进行探讨。
服务器公共组件实现 -- 继续来说主循环
前面我们只简单了解了下 mangos登录服的程序结构, 也发现了一些不足之处, 现在我们就来
看看如何提供一个更好的方案。
正如我们曾讨论过的, 为了游戏主逻辑循环的流畅运行, 所有比较耗时的 IO 操作都会分享到
单独的线程中去做,如网络 IO,数据库 IO 和日志 IO 等。当然,也有把这些分享到单独的进
程中去做的。
另外对于大多数服务器程序来说,在运行时都是作为精灵进程或服务进程的,所以我们并不
需要服务器能够处理控制台用户输入,我们所要处理的数据来源都来自网络。
这样,主逻辑循环所要做的就是不停要取消息包来处理,当然这些消息包不仅有来自客户端
的玩家操作数据包, 也有来自 GM服务器的管理命令, 还包括来自数据库查询线程的返回结果
消息包。这个循环将一直持续,直到收到一个通知服务器关闭的消息包。
主逻辑循环的结构还是很简单的,复杂的部分都在如何处理这些消息包的逻辑上。我们可以
用一段简单的伪码来描述这个循环过程:
while (Message* msg = getMessage())
{
if (msg 为服务器关闭消息 )
break;
处理 msg消息 ;
}
这里就有一个问题需要探讨了, 在 getMessage() 的时候, 我们应该去哪里取消息?前面我们
考虑过, 至少会有三个消息来源, 而我们还讨论过, 这些消息源的 IO 操作都是在独立的线程
中进行的,我们这里的主线程不应该直接去那几处消息源进行阻塞式的 IO 操作。
很简单, 让那些独立的 IO 线程在接收完数据后自己送过来就是了。 好比是, 我这里提供了一
个仓库, 有很多的供货商, 他们有货要给我的时候只需要交到仓库, 然后我再到仓库去取就
是了,这个仓库也就是消息队列。消息队列是一个普通的队列实现,当然必须要提供多线程
互斥访问的安全性支持,其基本的接口定义大概类 似这样:
IMessageQueue
{
void putMessage(Message*);
Message* getMessage();
}
网络 IO,数据库 IO 线程把整理好的消息包都加入到主逻辑循环线程的这个消息队列中便返
剩余10页未读,继续阅读
资源评论
资料大全
- 粉丝: 14
- 资源: 26万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功