Wow 服务器解析(一)

http://www.cppblog.com/Jedimaster/archive/2006/10/14/13674.aspx

 

Wow 服务器解析(一)

       最近抽空研究了一下 WOW 的服务器结构,也顺便从那些项目中又复习了一下 ManGOs template 方式下 SingleTon 的使用方法。不过有些不明白的,如果这样, SingleTon<Master> 这样的使用,如果传入的类型不同,难道传出的 static 是一样的?不可能吧,如果打印出 this 指针看看呢?抽空我再试试。 SingleTon 在游戏设计中是相当重要的设计模式,大家一定要好好学习。

认证过程

Wow 的服务器有两部分组成: Logon Server (以下简称 LS )和 Realm Server (以下简称 RS )。 LS 接受来自 Wow 客户端的连接,主要有以下几步完成:

检查客户端版本区域等信息,检察账号密码

开始 / 继续传送 Patch (如果有)

与客户端进行 SRP6 的加密会话,把生成的密匙写入数据库

根据客户端请求发送 Realms 列表

当客户端选择好 Realms 后,客户端就从 LS 断开,连接到 RS 上:

认证,使用刚才生成的客户端密匙

如通过,进行游戏循环的交互

RS LS 使用相同的数据库, SRP6 密匙被 LS 生成并写入 DB 后还要由 RS 读取出来进行下一步的认证。

 

Logon Server 详解

基本的连接过程如下:

客户端准备连接,发送 CMD_AUTH_LOGON_CHALLENGE 数据包,包含了所有登陆所需要的数据比如用户名密码等

服务端返回 CMD_AUTH_LOGON_CHALLENGE 数据包,填充字段包括有效验证,以及计算好的服务端 SRP6 数据

如果有效,客户端发送 CMD_AUTH_LOGON_PROOF 数据包,并把自己计算的 SRP6 数据填充进去

服务端进行验证,发送回 CMD_AUTH_LOGON_PROOF ,包含了 SRP6 验证的结果

如果一切正常,客户端发送 CMD_REALM_LIST 数据包,请求发送有效的 Realm

服务器回复 CMD_REALM_LIST 数据报,并填充过客户端需要的 Realm 数据

客户端的 Realm 列表每隔 3-4 秒就会从服务器端刷新一次。

  这个 SPR6 是一种什么样的加密手段呢?以前我也没有用过,看得最多的是 MD5SHA hash 算法。 SPR 算法吸取了 EKE 类型算法的优点进行了改进,非常适合于网络的认证服务,如果我没有记错, J2EE 包含了这个算法的实现。下面简单介绍一下 SRP6a 运作机制,原文见这里。

N     N = 2q + 1 q 是一个素数,下面所有的取模运算都和这个 N 有关

g     一个 N 的模数,应该是 2 个巨大的素数乘得来

k     k = H(N,G) SRP6 k = 3

s      User’s Salt

I      用户名

p     明文密码

H()  单向 hash 函数

^      求幂运算

u     随机数

a,b   保密的临时数字

A,B  公开的临时数字

x     私有密匙(从 p s 计算得来)

v     密码验证数字

其中 x  =  H(s,p) v = g ^ x s 是随机选择的, v 用来将来验证密码。

主机将 { I,s,v } 存入数据库。认证的过程如下:

 

客户向主机发送 I A = g ^ a a 是一个随机数)

主机向客户发送 s B = kv + g^b (发送 salt b 是一个随机数字)

双方同时计算 u = H(A,B)

客户计算机算 x = H(s,p) (开始 hash 密码), S = ((B - kg^x) ^ (a + ux) ) K = H(S) ,(开始计算会话 Key

主机计算 S = (Av^u)^b K = H(S) ,也生成会话 Key

 

为了完成认证,双方交换 Key ,各自进行如下的计算:

客户接收到来自主机的 key 后,计算 H(A,M,K)

同理,主机计算 M = H(H(N) xor H(g), H(I), s, A, B, K) ,验证是否合自己储存的数值匹配。至此完成验证过程。

 

三、 Realm Server 详解

LS 断开后,开始和 RS 认证:

连接到 RS ,向服务器发送 SMSG_AUTH_CHALLENGE 数据包,包含上次所用的随机种子

服务器发送回 SMSG_AUTH_CHALLENG 。客户端从服务器端发送回来的种子和 SRP6 数据中产生随机种子,生成 SHA1 字符串,用这些数据生成 CMSG_AUITH_SESSION 数据包,发送给服务端。

需要注意的是,这个过程是没有经过加密的。当服务端收到认证回复后,通过客户端产生的种子也生成一个 SHA1 串和来自客户端的进行对比,如果相同,一切 OK

 

下面看一下对账号创建的角色等操作进行分析。一个账号最多可以建 50 个角色吧,我还没有玩过,只是看了一下 Manual

 客户端发送一个 CMSG_CHAR_ENUM 数据包请求接受角色

服务端发送回包含所有角色信息的 CMSG_CHAR_ENUM 数据包

这里客户端可以对这些角色进行操作了, CMSG_CHAR_CREATE CMSG_CHAR_DELETE CMSG_CHAR_PLAYER_LOGIN

角色登陆完成后,服务器发送回 SMSG_CHAR_DATA 数据包


在游戏循环中是如何操作的呢?

如果玩家立刻退出游戏,那么客户端发送 CMSG_PLAYER_LOGOUT ,服务器回复 SMSG_LOGOUT_COMPLETE

如果玩家选择稍后退出游戏,发送 CMSG_LOGOUT_REQUEST 。服务端回复 SMSG_LOGOUT_RESPONSE 。如果玩家在倒计时阶段退出,发送 CMSG_PLAYER_LOGOUT ,那么玩家的角色依旧等倒计时完成后再退出。

如果玩家中断了退出继续游戏,发送 CMSG_LOGOUT_CANCEL ,服务器回复 SMSG_LOGOUT_CANCEL_ACK

阅读更多
换一批

没有更多推荐了,返回首页