第一范文网 - 专业文章范例文档资料分享平台

传奇源码分析

来源:用户分享 时间:2025/8/21 14:49:35 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

数据库管理类,做底层数据库操作。

3) MainWndProc窗口回调函数OnCommand: IDM_STARTSERVICE:

创建LoadAccountRecords线程

a). UPDATE TBL_ACCOUNT重置帐户验证状态。 b). 读服务器列表(TBL_SERVERINFO, selGate服务器),加入g_xGameServerList 遍历xGameServerList列表,把服务器信息加入到一个字符数组g_szServerList中。

c). 启动InitServerThreadForMsg线程。

d). 调用InitServerSocket函数创建两个线程: AcceptThread线程:

ServerWorkerThread线程: 调用InitServerSocket函数创建两个线程: 1) AcceptThread线程:

Accept之后生成一个CGateInfo对象,CGateInfo->sock = Accept; 客户端Socket值赋值给结构体。记录客户相关信息。新的套接字句柄用

CreateIoCompletionPort关联到完成端口,然后发出一个异步的WSASend或者WSARecv调用(pNewUserInfo->Recv();接收客户端消息),因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收数据的操作由WINDOWS系统去做。然后把CGateInfo对象加入g_xGateList中。在客户accept之后,投递一个I/O(recv)。

分析一下g_xGateList发现,每个CGateInfo里有sock; xUserInfoList,g_SendToGateQ,该网关的相关信息依次(网关对应的sock, 用户列列信息,消息队列),可以为多个LoginGate登录网关服务。

2) ServerWorkerThread线程:

ServerWorkerThread线程工作原理:

循环调用GetQueuedCompletionStatus()函数来得到IO操作结果。阻塞函数。当WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成的

WSASend/WSARecv的结果。然后接着发出WSASend/WSARecv,并继续下一次循环阻塞在GetQueuedCompletionStatus()这里。

a).if (g_fTerminated) 线程结束前:循环遍历g_xGateList,取出pGateInfo关闭套接字,并删除节点。dwBytesTransferred =0 ,关闭该服务器套接字。 b).while ( pGateInfo->HasCompletionPacket() ) 验证消息格式。 case '-': 发送心跳数据包到每个LoginGate服务器。

case 'A': 处理每个LoginGat服务器转发的客户端的消息增加到各自网关

(CGateInfo)g_SendToGateQ队列中,然后ThreadFuncForMsg线程进行验证后再发送消息到各个LoginGate服务器。

pGateInfo->ReceiveSendUser(&szTmp[2]);

case 'O': 处理每个网关Accept客户端后增加pUserInfo用户信息到各自网关

的xUserInfoList列表中。

pGateInfo->ReceiveOpenUser(&szTmp[2]);

case 'X': 处理每个网关收到客户端Socket关闭之后发送过来的消息。设置该网关socket相应状态。

pGateInfo->ReceiveCloseUser(&szTmp[2]);

case 'S': GameSvr服务器发送的消息,更新TBL_ACCOUNT,验证字段,说明用户已下线,下次登录必须先到LoginSvr服务器再次验证。 pGateInfo->ReceiveServerMsg(&szTmp[2]); case 'M': GameSvr服务器发送的消息,创建一个用户的消息,把用户ID,密码,名字插入TBL_ACCOUNT表中插入成功返回SM_NEWID_SUCCESS,否则

SM_NEWID_FAIL,把在信息前加#,信息后加! 不做TBL_ACCOUNTADD表的添加,只增加TBL_ACCOUNT表信息。

‘A’:是LoginGate 服务器转发客户端消息到g_xMsgQueue队列, 由ThreadFuncForMsg线程处理后,转发到各个loginGate服务器 继续投递I/O操作。

启动InitServerThreadForMsg 创建ThreadFuncForMsg线程。c

收到loginGate服务器发送过来的消息之后,ServerWorkerThread经过数据包分析之后(case 'A'),把客户端的消息,写入g_SendToGateQ队列中,然后在本线程中再进行处理。

遍历g_SendToGateQ队列中数据,验证数据包是否正确(#!字符)根据DefaultMsg.wIdent标志

case CM_IDPASSWORD: 处理登陆业务

遍历xUserInfoList用户列表信息,到数据库表TBL_ACCOUNT中找相应信息,如果失败发送(SM_ID_NOTFOUND, SM_PASSWD_FAIL)消息,否则发送SM_PASSOK_SELECTSERVER+ g_szServerList(SelGate服务器列表消息) SelGate服务器列表消息(对应TBL_SERVERINFO数据库表中数据),供用户选择登录的SelGate服务器。

CM_SELECTSERVER: 选择服务器(SelGate)

遍历xUserInfoList用户列表信息,根据socket,找到用户密钥,消息解密后,遍历g_xGameServerList列表,把用户选择的SelGate服务器转化为IP地址,发送至LoginGate服务器,再转发至客户端。设置该用户SelServer的标志状态。从该网关的xUserInfoList用户列表中删除该用户。

CM_ADDNEWUSER: 新注册用户

判断用户名是否已存在,失败发送SM_NEWID_FAIL消息,成功,写插入表数据,并发送SM_NEWID_SUCCESS消息到 LoginGate服务器,转发至客户端。

IDM_STOPSERVICE: 停止服务(IOCP模型Server响应客户端请求)

Close -> OnCommand(IDM_STOPSERVICE, 0L); ->g_fTerminated = TRUE; 三个线程退出。

主要流程:

服务启动后,LoginSvr启动了AcceptThread,和ServerWorkerThread线程,AcceptThread线程接收loginGate,GameSvr服务器连接,加入g_xGateList网关列表中,ServerWorkerThread线程从完成端口取得刚完成的WSASend/WSARecv的结果后,进行分析处理两个服务器发送来的消息。服务启动同时,启动ThreadFuncForM

sg线程,该线程从g_xMsgQueue(iocp读到的loginGate服务器发来的数据)中取出数据,处理数据。投递I/O,利用IOCP模型,发送到loginGate服务器。 传奇源码分析-客户端(游戏逻辑处理源分析二)

5.接受登录成功后,接收GameSrv服务器发送的消息:

接收GameGate发送的消息:CClientSocket::OnSocketMessage的FD_READ事件中,PacketQ.PushQ((BYTE*)pszPacket);把接收到的消息,压入PacketQ队列中。处理PacketQ队列数据是由CGameProcess::Load()时调用OnTimer在CGameProcess::OnTimer中处理的, 处理过程为:

OnMessageReceive; ProcessPacket();

ProcessDefaultPacket();

OnMessageReceive函数;

1. 判断是否收到心跳数据包,发送'*',发送心跳数据包。 2. 调用OnSocketMessageRecieve函数。这个函数里面详细处理了客户端的游戏执行逻辑。如果是‘+’开头(数据包)则调用OnProcPacketNotEncode处理这种类型数据包。否则得到_TDEFAULTMESSAGE数据包,进行游戏逻辑处理。 OnProcPacketNotEncode说明:

收到GameSrv服务器的相应消息:

\:可以执行动作。 m_bMotionLock为假。 \:不允许执行动作。人物被拉回移动前位置。 \: \: \: \: \: \: \:

3. CGameProcess::OnSocketMessageRecieve(char *pszMsg)函数。处理游戏相关的消息。

SM_SENDNOTICE: 服务器提示信息:

SM_NEWMAP: 用户登录后,服务器发送的初始化地图消息。

SM_LOGON: 用户登录消息(服务器处理后返回结果)。用户登录成功后,在本地创建游戏对象,并发送消息,请求返回用户物品清单(魔法,等级,物品等)。 SM_MAPDESCRIPTION: 得到服务器发送的地图的描述信息。 SM_ABILITY:服务器发送的本玩家金钱,职业信息。 SM_WINEXP:

SM_SUBABILITY : 服务器发送的玩家技能(魔法,杀伤力,速度,毒药,中毒恢复,生命恢复,符咒恢复)

SM_ SM_SENDMYMAGIC: 用户魔法列表信息。 SM_MAGIC_LVEXP: 魔法等级列表。

SM_BAGITEMS:用户物品清单 (玩家CM_QUERYBAGITEMS消息) SM_SENDUSEITEMS:用户装备清单 SM_ADDITEM: 拣东西 SM_DELITEM: 丢弃物品。 等等。

4. 部分数据未处理,加入m_xWaitPacketQueue队列中由ProcessPacket处理。

新登录游戏玩家:在OnSocketMessageRecieve函数中依次收到的消息为: 1. GameSrv 服务器ProcessLogin线程返回GameGate服务器后返回的: AddProcess(this, RM_LOGON, 0, 0, 0, 0, NULL);加入登录消息。 SM_NEWMAP, SM_LOGON, SM_USERNAME, SM_MAPDESCRIPTION消息 AddProcess(this, RM_ABILITY, 0, 0, 0, 0, NULL); 等级 SM_ABILITY

AddProcess(this, RM_SUBABILITY, 0, 0, 0, 0, NULL); SM_SUBABILITY

AddProcess(this, RM_DAYCHANGING, 0, 0, 0, 0, NULL); 校时 SM_DAYCHANGING

AddProcess(this, RM_SENDUSEITEMS, 0, 0, 0, 0, NULL); 装备 SM_SENDUSEITEMS

AddProcess(this, RM_SENDMYMAGIC, 0, 0, 0, 0, NULL); 魔法 SM_SENDMYMAGIC

客户端收到消息后相应的处理: SM_NEWMAP 接受地图消息 OnSvrMsgNewMap

初始化玩家坐标,m_xMyHero.m_wPosX = ptdm->wParam; m_xMyHero.m_wPosY = ptdm->wTag; 加载地图文件 m_xMap.LoadMapData(szMapName);

设置场景。 m_xLightFog.ChangeLightColor(dwFogColor);

SM_LOGON 返回登录消息 OnSvrMsgLogon

m_xMyHero.Create初始化玩家信息(头发,武器,加载图片等),设置玩家

搜索更多关于: 传奇源码分析 的文档
传奇源码分析.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c6l2ye1oaqr0fluh9bay7_4.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top