这几天有些空闲时间,把改编自MangOS的魔兽私服Trinitycore代码梳理一下,也给有这方面兴趣
的童鞋一个交流空间,可能会连载15篇左右,大家慢慢看
首先把整体架构网络层说一下
打开整个工程,找到Trinitycore项目,game这个库引用了framework,shared等库,以后有时间再一一介绍
Trinitycore_build_8128_for_client_333a/src/trinitycore/Main.cpp
这个主函数其实就是提取配置文件名称和在Windows环境下以WIN32 服务方式使用的三种情况,这种编程手法
在我们很多项目中都很常见,就不多说了
最主要的就是这句
return sMaster.Run();
这里最重要的一个步骤就是
void World::SetInitialWorldSettings()
其实我们做过网游开发的人都应该知道,这就是加载服务器的各种资源文件,初始化场景,初始化脚本引擎,
序列化文件读取之类的步骤,每款游戏各有不同,但都是启动前最耗时间的一段程序
然后就是启动4个线程
ACE_Based::Thread world_thread(new WorldRunnable);
world_thread.setPriority(ACE_Based::Highest);
ACE_Based::Thread* cliThread = NULL;
cliThread = new ACE_Based::Thread(new CliRunnable);
ACE_Based::Thread rar_thread(new RARunnable);
FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
接着取得IP,和端口开始网络服务
int
WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address)
这个函数很明显,大家都可以找到,也可以很轻松找到下一个函数
int
WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address)
在分析这个函数时不得不去仔细阅读一下另一个类的声明,只看一部分就够了
typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler;
class WorldSocket : protected WorldHandler
{
public:
/// Declare some friends
friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >;
friend class WorldSocketMgr;
friend class ReactorRunnable;
/// Declare the acceptor for this class
typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor;----------这个模板定义很重要
WorldSocket 的 open 方法由接受器工厂在连接建立之后调用的时候调用
这样思路就完全清晰了
int WorldSocket::open (void *a)
函数中通过
if (sWorldSocketMgr->OnSocketOpen (this) == -1)
----这个方法,把这个SOCKET对象放入了一个合适的线程中
return -1;
最后就是网络包对应逻辑处理的流程
WorldSocket::handle_input (ACE_HANDLE)
---WorldSocket::handle_input_missing_data
---WorldSocket::handle_input_payload
---WorldSocket::ProcessIncoming (WorldPacket* new_pct)
---最后进入
int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
此函数最重要的部分,列出如下
//这句话生成了玩家的session,并保存
ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale), -1);
m_Crypt.Init(&K);
m_Session->LoadGlobalAccountData();
m_Session->LoadTutorialsData();
m_Session->ReadAddonsInfo(recvPacket);
// In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
ACE_OS::sleep (ACE_Time_Value (0, 10000));
sWorld.AddSession (m_Session);
网络这一块真是难以用很漂亮的语言描述清楚,中间再加一个小插曲
WorldSocketMgr.cpp中定义了一个主动对象类,这个就是sWorldSocketMgr->OnSocketOpen函数中
分担各个WorldSocket的那个线程类
virtual int svc ()
{
DEBUG_LOG ("Network Thread Starting");
WorldDatabase.ThreadStart();
ACE_ASSERT (m_Reactor);