AI服务器的设计与实现.docx

上传人:b****7 文档编号:8762262 上传时间:2023-02-01 格式:DOCX 页数:25 大小:23.99KB
下载 相关 举报
AI服务器的设计与实现.docx_第1页
第1页 / 共25页
AI服务器的设计与实现.docx_第2页
第2页 / 共25页
AI服务器的设计与实现.docx_第3页
第3页 / 共25页
AI服务器的设计与实现.docx_第4页
第4页 / 共25页
AI服务器的设计与实现.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

AI服务器的设计与实现.docx

《AI服务器的设计与实现.docx》由会员分享,可在线阅读,更多相关《AI服务器的设计与实现.docx(25页珍藏版)》请在冰豆网上搜索。

AI服务器的设计与实现.docx

AI服务器的设计与实现

经过一段时间的设计与完善,我们游戏的AI服务器已经达到了基本的性能要求,目前单个AI进程可同时运行4000+个频繁的AI对象。

在前面一篇博客中已经提到过,AI服务器的主逻辑循环是单线程的,这个线程上运行了数千个用户级线程,每个用户级线程运行一个AI对象。

AI对象被激活之后就会运行一段lua脚本,以实现AI逻辑.

之所以采用用户级线程(windows下是fiber,linux下使用ucontext)的方案,是因为AI的实现使用了大量的远程调用,如果使用同步调用势必导致主线程的阻塞,从而影响AI服务器的性能。

采用异步调用又导致了逻辑的过分复杂。

而用户级线程正好解决了这些问题,向上提供了一个同步调用的接口,又不会导致主线程的阻塞(当一个用户级线程处于等待结果的状态下,调度器可以选择另一个用户级线程来运行)。

AI服务器的主要构件是用户级线程调度器,和一个用户级线程池,服务器启动后会产生一组用户级线程序,并且在每个线程上创建一个lua虚拟机。

 

基本的设计思路已经介绍完毕,下面介绍各个主要的组成部分:

首先是主循环:

viewplain

1.void CAIApp:

:

Process()     

2.{     

3.    psarmor l_pa(*this);     

4.    Scheduler:

:

Init();     

5.    while(!

GetExitTaskFlag() && l_pa(psobj:

:

realtime))     

6.    {     

7.        //如果到game的连接断开,执行错误处理并尝试重连     

8.        while(!

m_flag2Game)     

9.        {     

10.            //连接断了,要清除所有已经绑定的Ai对象     

11.            //g_AiObjMap为空的话不可能有任务在运行     

12.            if(!

g_AiObjMap.empty())     

13.            {        

14.                //连接已经断开,停掉所有运行的AI     

15.                {     

16.                    std:

:

map >:

:

iterator it =  g_AiObjMap.begin();     

17.                    std:

:

map >:

:

iterator end =  g_AiObjMap.end();     

18.                    for( ; it !

= end; ++it)     

19.                        it->second->StopAi();     

20.                }     

21.                //清理active列表     

22.                Scheduler:

:

ClearActiveList();     

23.                //清理timeout列表     

24.                Scheduler:

:

ClearTimeOut();     

25.                {     

26.                    std:

:

cout << "到gameserver的连接断开,清除所有绑定对象" << std:

:

endl;     

27.                    std:

:

map >:

:

iterator it =  g_AiObjMap.begin();     

28.                    std:

:

map >:

:

iterator end =  g_AiObjMap.end();     

29.                    for( ; it !

= end; ++it)     

30.                        it->second = 0;     

31.                    g_AiObjMap.clear();     

32.                }     

33.                //清理aigroup      

34.                {     

35.                    std:

:

map >:

:

iterator it =  g_GroupMap.begin();     

36.                    std:

:

map >:

:

iterator end =  g_GroupMap.end();     

37.                    for( ; it !

= end; ++it)     

38.                        it->second = 0;     

39.                    g_GroupMap.clear();     

40.                }     

41.            }     

42.            m_pToGame = 0;     

43.            while(m_pToGame._nil())     

44.            {     

45.                rptr l_sock   =g_aiapp->Connect(g_aiapp->m_config.m_gameip,g_aiapp->m_config.m_gameport);     

46.                if(l_sock._nil())     

47.                {     

48.                    std:

:

cout << "连接game失败!

5秒后重试..." << std:

:

endl;     

49.                }     

50.                else    

51.                {     

52.                    printf("连接game成功...");     

53.                    WPacket l_wpk   =g_aiapp->GetWPacket();     

54.                    l_wpk.WriteCmd(CMD_AM_AILOGIN);     

55.                    l_wpk.WriteShort(g_aiapp->m_config.m_mapcount);     

56.                    for( int i = 0;i < g_aiapp->m_config.m_mapcount; ++i)     

57.                    {     

58.                        l_wpk.WriteString(g_aiapp->m_config.m_names[i].c_str());     

59.                    }     

60.                    l_sock->SendData(l_wpk);     

61.                    m_pToGame = l_sock;     

62.                    m_flag2Game = true;     

63.                    break;     

64.                }     

65.                Sleep(5000);     

66.            }     

67.        }     

68.        Scheduler:

:

Schedule();     

69.        PeekPacket(50);     

70.    }     

71.    Scheduler:

:

Destroy();     

72.}    

73.void CAIApp:

:

Process()  

74.{  

75. psarmor l_pa(*this);  

76. Scheduler:

:

Init();  

77. while(!

GetExitTaskFlag() && l_pa(psobj:

:

realtime))  

78. {  

79.  //如果到game的连接断开,执行错误处理并尝试重连  

80.  while(!

m_flag2Game)  

81.  {  

82.   //连接断了,要清除所有已经绑定的Ai对象  

83.   //g_AiObjMap为空的话不可能有任务在运行  

84.   if(!

g_AiObjMap.empty())  

85.   {   

86.    //连接已经断开,停掉所有运行的AI  

87.    {  

88.     std:

:

map >:

:

iterator it =  g_AiObjMap.begin();  

89.     std:

:

map >:

:

iterator end =  g_AiObjMap.end();  

90.     for( ; it !

= end; ++it)  

91.      it->second->StopAi();  

92.    }  

93.    //清理active列表  

94.    Scheduler:

:

ClearActiveList();  

95.    //清理timeout列表  

96.    Scheduler:

:

ClearTimeOut();  

97.    {  

98.     std:

:

cout << "到gameserver的连接断开,清除所有绑定对象" << std:

:

endl;  

99.     std:

:

map >:

:

iterator it =  g_AiObjMap.begin();  

100.     std:

:

map >:

:

iterator end =  g_AiObjMap.end();  

101.     for( ; it !

= end; ++it)  

102.      it->second = 0;  

103.     g_AiObjMap.clear();  

104.    }  

105.    //清理aigroup   

106.    {  

107.     std:

:

map >:

:

iterator it =  g_GroupMap.begin();  

108.     std:

:

map >:

:

iterator end =  g_GroupMap.end();  

109.     for( ; it !

= end; ++it)  

110.      it->second = 0;  

111.     g_GroupMap.clear();  

112.    }  

113.   }  

114.   m_pToGame = 0;  

115.   while(m_pToGame._nil())  

116.   {  

117.    rptr l_sock =g_aiapp->Connect(g_aiapp->m_config.m_gameip,g_aiapp->m_config.m_gameport);  

118.    if(l_sock._nil())  

119.    {  

120.     std:

:

cout << "连接game失败!

5秒后重试..." << std:

:

endl;  

121.    }  

122.    else  

123.    {  

124.     printf("连接game成功...");  

125.     WPacket l_wpk =g_aiapp->GetWPacket();  

126.     l_wpk.WriteCmd(CMD_AM_AILOGIN);  

127.     l_wpk.WriteShort(g_aiapp->m_config.m_mapcount);  

128.     for( int i = 0;i < g_aiapp->m_config.m_mapcount; ++i)  

129.     {  

130.      l_wpk.WriteString(g_aiapp->m_config.m_names[i].c_str());  

131.     }  

132.     l_sock->SendData(l_wpk);  

133.     m_pToGame = l_sock;  

134.     m_flag2Game = true;  

135.     break;  

136.    }  

137.    Sleep(5000);  

138.   }  

139.  }  

140.  Scheduler:

:

Schedule();  

141.  PeekPacket(50);  

142. }  

143. Scheduler:

:

Destroy();  

144.}  

  

 

上面代码的主要作用就是尝试连接gameserver,如果连接成功就在循环中调用调度器的调度函数以选择合适的用户级线程运行。

PeekPacket(50);会从网络层提取网络包,如果没有网络包则会休眠最多50毫秒.

下面在来看看调度器:

viewplain

1.void Scheduler:

:

Schedule()     

2.{     

3.    //将所有等待添加到m_activeList中的纤程都添加进去     

4.    {     

5.        for(unsigned int i = 0; i < pending_index; ++i)     

6.        {     

7.            uthread *ut = m_uthreads[m_pendingAdd[i]];     

8.            ut->SetNext(0);     

9.            if(m_active_tail)     

10.            {     

11.                m_active_tail->SetNext(ut);     

12.                m_active_tail = ut;     

13.            }     

14.            else    

15.            {     

16.                m_active_head = m_active_tail = ut;     

17.            }     

18.        }     

19.        pending_index = 0;     

20.    }     

21.    uthread *cur = m_active_head;     

22.    uthread *pre = NULL;     

23.    while(cur)     

24.    {     

25.        g_aiapp->PeekPacket(0);     

26.        m_curuid = cur->GetUid();     

27.        SwitchToFiber(cur->GetUContext());     

28.        m_curuid = -1;     

29.        unsigned char status = cur->GetStatus();     

30.        //当纤程处于以下状态时需要从可运行队列中移除     

31.        if(status == DEAD || status == SLEEP || status == WAIT4EVENT || status == UNACTIVED || status == YIELD)     

32.        {     

33.            //删除首元素     

34.            if(cur == m_active_head)     

35.            {     

36.                //同时也是尾元素     

37.                if(cur == m_active_tail)     

38.                    m_active_head = m_active_tail = NULL;     

39.                else    

40.                    m_active_head = cur->Next();     

41.            }     

42.            else if(cur == m_active_tail)     

43.            {     

44.                    pre->SetNext(NULL);     

45.                    m_active_tail = pre;     

46.            }     

47.            else    

48.                pre->SetNext(cur->Next());     

49.            uthread *tmp = cur;     

50.            cur = cur->Next();     

51.            tmp->SetNext(0);     

52.            //如果仅仅是让出处理器,需要重新投入到可运行队列中     

53.            if(status == YIELD)     

54.                Add2Active(tmp);     

55.                 

56.        }     

57.        else    

58.        {     

59.            pre = cur;     

60.            cur = cur->Next();     

61.        }     

62.    }     

63.    //看看有没有timeout的纤程     

64.    {     

65.        uLong now = dbc:

:

GetTickCount();     

66.        while(m_timeoutlist.Min() !

=0 && m_timeoutlist.Min() <= now)     

67.        {     

68.            st_timeout *timeout = m_timeoutlist.PopMin();     

69.            if(timeout->ut->GetStatus() == WAIT4EVENT || timeout->ut->GetStatus() == SLEEP)     

70.            {     

71.                timeout->ut->wakeuptick = timeout->_timeout;     

72.                Add2Active(timeout->ut);     

73.            }     

74.        }     

75.    }     

76.}    

77.void Scheduler:

:

Schedule()  

78.{  

79. //将所有等待添加到m_activeList中的纤程都添加进去  

80. {  

81.  for(unsigned int i = 0; i < pending_index; ++i)  

82.  {  

83.   uthread *ut = m_uthreads[m_pendingAdd[i]];  

84.   ut->SetNext(0);  

85.   if(m_active_tail)  

86.   {  

87.    m_active_tail->SetNext(ut);  

88.    m_active_tail = ut;  

89.   }  

90.   else  

91.   {  

92.    m_active_head = m_active_tail = ut;  

93.   }  

94.  }  

95.  pending_index = 0;  

96. }  

97. uthread *cur = m_active_head;  

98. uthread *pre = NULL;  

99. while(cur)  

100. {  

101.  g_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 哲学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1