青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 311, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
本篇將介紹客戶端與游戲邏輯服務(wù)器連接建立以后,mangosd如何接收、解析和處理客戶端發(fā)過來的協(xié)議。本篇不再討論mangosd與客戶端的認證及建立最終RC4流加密的過程,想了解這部分內(nèi)容請看該系列的第一篇

 

 

一、acceptor socket的監(jiān)聽啟動及注冊

mangosd的main ()函數(shù)調(diào)用單例對象sMaster的Run ()函數(shù),啟動監(jiān)聽socket的代碼如下:

 

   1: int Master::Run()
   2: {
   3:     ........
   4:  
   5:     ///- Launch the world listener socket
   6:     uint16 wsport = sWorld.getConfig (CONFIG_UINT32_PORT_WORLD);
   7:     std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0");
   8:  
   9:     if (sWorldSocketMgr->StartNetwork (wsport, bind_ip) == -1)
  10:     {
  11:         sLog.outError ("Failed to start network");
  12:         Log::WaitBeforeContinueIfNeed();
  13:         World::StopNow(ERROR_EXIT_CODE);
  14:         // go down and shutdown the server
  15:     }
  16:  
  17:     sWorldSocketMgr->Wait ();
  18:  
  19:     ........
  20: }

 

mangosd用WorldSocketMgr類來管理socket。StartNetwork ()會調(diào)用StartReactiveIO ()來啟動監(jiān)聽socket,處理代碼如下:

   1: int WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address)
   2: {
   3:     ........
   4:  
   5:     //(1)
   6:     m_NetThreadsCount = static_cast<size_t> (num_threads + 1);
   7:     m_NetThreads = new ReactorRunnable[m_NetThreadsCount];
   8:  
   9:     // -1 means use default
  10:     m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1);
  11:     m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536);
  12:     if ( m_SockOutUBuff <= 0 )
  13:     {
  14:         sLog.outError ("Network.OutUBuff is wrong in your config file");
  15:         return -1;
  16:     }
  17:  
  18:     //(2)
  19:     WorldSocket::Acceptor *acc = new WorldSocket::Acceptor;
  20:     m_Acceptor = acc;
  21:  
  22:     ACE_INET_Addr listen_addr (port, address);
  23:     if (acc->open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1)
  24:     {
  25:         sLog.outError ("Failed to open acceptor ,check if the port is free");
  26:         return -1;
  27:     }
  28:  
  29:     //(3)
  30:     for (size_t i = 0; i < m_NetThreadsCount; ++i)
  31:         m_NetThreads[i].Start ();
  32:  
  33:     return 0;
  34: }

(1)ReactorRunnable類繼承了ACE_Task_Base,ACE_Task_Base 是ACE 中的任務(wù)或主動對象“處理結(jié)構(gòu)”的基類。在ACE 中使用了此類來實現(xiàn)主動對象模式。所有希望成為“主動對象”的對象都必須從此類派生。可以把ACE_TASK 看作是更高級的、更為面向?qū)ο蟮木€程類[1]。ACE_Task_Base調(diào)用時繼承類必須重寫svc方法,并且在使用時保證調(diào)用了activate ()方法。

(2)指定監(jiān)聽地址,端口并把Acceptor綁定到第一個線程的Reactor上。啟動Acceptor開始監(jiān)聽網(wǎng)絡(luò)IO。

(3)啟動所有線程,每個線程上有一個單獨的ACE_Reactor* m_Reactor;,這里的Reactor使用的是多線程的ACE_TP_Reactor。可以各自單獨完成事件的多路復(fù)用。

 

 

二、線程體函數(shù)

線程體函數(shù)ReactorRunnable::svc () 如下:

   1: virtual int svc ()
   2: {
   3:     //(1)
   4:     WorldDatabase.ThreadStart ();
   5:     
   6:     SocketSet::iterator i, t;
   7:     while (!m_Reactor->reactor_event_loop_done ())
   8:     {
   9:         // dont be too smart to move this outside the loop
  10:         // the run_reactor_event_loop will modify interval
  11:         ACE_Time_Value interval (0, 10000);
  12:  
  13:         //(2)
  14:         if (m_Reactor->run_reactor_event_loop (interval) == -1)
  15:             break;
  16:  
  17:         //(3)
  18:         AddNewSockets ();
  19:  
  20:         for (i = m_Sockets.begin (); i != m_Sockets.end ();)
  21:         {
  22:             //(4)
  23:             if ((*i)->Update () == -1)
  24:             {
  25:                 t = i;
  26:                 ++i;
  27:                 (*t)->CloseSocket ();
  28:                 (*t)->RemoveReference ();
  29:                 --m_Connections;
  30:                 m_Sockets.erase (t);
  31:             }
  32:             else
  33:                 ++i;
  34:         }
  35:     }
  36:  
  37:     WorldDatabase.ThreadEnd ();
  38:     DEBUG_LOG ("Network Thread Exitting");
  39:  
  40:     return 0;
  41: }

(1)會調(diào)用mysql_thread_init ()函數(shù),初始化與該線程相關(guān)的變量。

(2)run_reactor_event_loop ()函數(shù)為多路復(fù)用的等待函數(shù),當(dāng)注冊的事件發(fā)生、運行超時或者出現(xiàn)錯誤時返回。

(3)AddNewSockets ()函數(shù)會將緩存在m_NewSockets里的新到達的socket添加到SocketSet m_Sockets;里,同時檢查并處理m_Sockets;里已經(jīng)closed的socket。

(4)循環(huán)每一個WorldSocket,調(diào)用其Update ()方法,這里只處理每個socket的handle_output,即每個在此線程上的寫事件,向客戶端發(fā)送數(shù)據(jù)。下一節(jié)詳細介紹:

 

 

三、WorldSocket::Update () 方法

Update方法用于處理每個socket的輸出:

   1: int WorldSocket::Update (void)
   2: {
   3:     if (closing_)
   4:         return -1;
   5:  
   6:     //(1)
   7:     if (m_OutActive || m_OutBuffer->length () == 0)
   8:         return 0;
   9:  
  10:     return handle_output (get_handle ());
  11: }

(1)m_OutBuffer有數(shù)據(jù)時才會調(diào)用handle_output,handle_output ()用于處理輸出,如果輸出不能一次性做完,會調(diào)用schedule_wakeup_output ()再次激活write事件。當(dāng)輸出處理完畢后則調(diào)用cancel_wakeup_output ()取消激活write事件,使reactor恢復(fù)到正常的loop ()循環(huán)中。詳細過程如下:

 

   1: int WorldSocket::handle_output (ACE_HANDLE)
   2: {
   3:     //(1)
   4:     ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);
   5:  
   6:     if (closing_)
   7:         return -1;
   8:  
   9:     const size_t send_len = m_OutBuffer->length ();
  10:     if (send_len == 0)
  11:         return cancel_wakeup_output (Guard);
  12:  
  13: #ifdef MSG_NOSIGNAL
  14:     ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL);
  15: #else
  16:     ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len);
  17: #endif // MSG_NOSIGNAL
  18:  
  19:     if (n == 0)
  20:         return -1;
  21:     else if (n == -1)
  22:     {
  23:         if (errno == EWOULDBLOCK || errno == EAGAIN) //----------(2)
  24:             return schedule_wakeup_output (Guard);
  25:  
  26:         return -1;
  27:     }
  28:     else if (n < (ssize_t)send_len) //now n > 0      //----------(3)
  29:     {
  30:         m_OutBuffer->rd_ptr (static_cast<size_t> (n));
  31:  
  32:         // move the data to the base of the buffer
  33:         m_OutBuffer->crunch ();
  34:  
  35:         return schedule_wakeup_output (Guard);
  36:     }
  37:     else //now n == send_len                         //----------(4)
  38:     {
  39:         m_OutBuffer->reset ();
  40:  
  41:         if (!iFlushPacketQueue ())
  42:             return cancel_wakeup_output (Guard);
  43:         else
  44:             return schedule_wakeup_output (Guard);
  45:     }
  46:  
  47:     ACE_NOTREACHED (return 0);
  48: }

(1)對m_OutBuffer加鎖。

(2)考慮信號打斷的情況等,暫時不能寫。

(3)只發(fā)送了部分數(shù)據(jù)則繼續(xù)wakeup該線程對應(yīng)的Reactor。

(4)檢查m_OutBuffer數(shù)據(jù)發(fā)送完畢同時等待buffer(PacketQueueT m_PacketQueue;)里已經(jīng)沒有數(shù)據(jù)時,cancel wakeup讓Reactor恢復(fù)正常。

 

 

四、socket到對應(yīng)線程的指派

上一節(jié)內(nèi)容可以看到線程內(nèi)如何處理socket,及新到達的socket。但從第一節(jié)中可知只有第一個線程注冊為acceptor線程,那么新連接到達時,是如何被指派到對應(yīng)的“接待”線程的呢?

可以先看一下ACE_Acceptor的處理時序圖:

 


圖3.1 連接到達處理時序 [2]

 

上圖可以看出,當(dāng)連接到達時,acceptor會調(diào)用對應(yīng)的SVC_HANDLER的open ()函數(shù),在mangosd里就是acceptor對應(yīng)的int WorldSocket::open (void *a),如下:

   1: int WorldSocket::open (void *a)
   2: {
   3:     ........
   4:  
   5:     // Hook for the manager.
   6:     if (sWorldSocketMgr->OnSocketOpen (this) == -1)
   7:         return -1;
   8:  
   9:     ........
  10: }

 

OnSocketOpen方法:

   1: int WorldSocketMgr::OnSocketOpen (WorldSocket* sock)
   2: {
   3:     ........
   4:  
   5:     // we skip the Acceptor Thread
   6:     size_t min = 1;
   7:  
   8:     MANGOS_ASSERT (m_NetThreadsCount >= 1);
   9:  
  10:     //(1)
  11:     for (size_t i = 1; i < m_NetThreadsCount; ++i)
  12:         if (m_NetThreads[i].Connections () < m_NetThreads[min].Connections ())
  13:             min = i;
  14:  
  15:     return m_NetThreads[min].AddSocket (sock);
  16: }

(1)將WorldSocket均衡的分配給每個線程。AddSocket ()將socket添加到m_NewSockets中做緩存,待該線程自行調(diào)用AddNewSockets ()添加到處理隊列里。

 

 

總結(jié):

mangosd對socket的處理因為使用了ACE,邏輯處理代碼相對比較簡單,寫事件的異常處理主要涉及

(1)一次不能寫完則不斷的wakeup Reactor。

(2)信號中斷等錯誤的判斷。似乎這里并沒有考慮全面(見附錄)

(3)使用另一個buffer緩存,因?qū)懢彺鎚_OutBuffer滿而帶來的多出的數(shù)據(jù)。

 

References:

[1] http://blog.csdn.net/yecao_kinux/article/details/1546914

[2] http://postfiles12.naver.net/data41/2009/4/11/187/33_kbkim007.jpg?type=w3

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            91久久精品日日躁夜夜躁国产| 欧美成年人视频| 美女久久一区| 久久久亚洲国产天美传媒修理工| 午夜久久一区| 翔田千里一区二区| 久久久久久久999| 欧美国产日本在线| 日韩网站免费观看| 亚洲综合视频1区| 久久久久久久久久码影片| 久久综合网hezyo| 欧美日韩综合久久| 国产在线视频欧美| 亚洲精品国产精品国自产在线 | 国产伦理精品不卡| 国产一区清纯| 一区二区三区精品视频| 欧美一级片在线播放| 美女免费视频一区| 99精品视频网| 久久理论片午夜琪琪电影网| 欧美日韩国产精品自在自线| 国产亚洲电影| 国产精品99久久久久久www| 欧美亚洲视频一区二区| 欧美成人激情视频免费观看| 一区二区三区四区国产精品| 久久人人97超碰国产公开结果| 欧美视频在线观看免费| 在线看国产一区| 午夜精品久久久久久久蜜桃app | 欧美福利一区| 亚洲一区在线播放| 欧美激情综合色综合啪啪| 国产一区二区三区在线免费观看 | 伊人男人综合视频网| 亚洲午夜羞羞片| 欧美激情 亚洲a∨综合| 欧美在线视频免费| 日韩一级精品视频在线观看| 猛干欧美女孩| 日韩亚洲视频在线| 美日韩精品免费观看视频| 国产精品一区二区在线观看网站 | 久久久免费av| 中文国产成人精品久久一| 狼狼综合久久久久综合网 | 国产一区亚洲一区| 亚洲视频精品| 亚洲精品一区在线观看香蕉| 毛片基地黄久久久久久天堂| 狠狠干综合网| 久久一区二区三区四区五区| 亚洲自拍偷拍网址| 国产精品看片资源| 亚洲男女自偷自拍图片另类| 日韩视频免费在线观看| 欧美啪啪成人vr| 一本色道**综合亚洲精品蜜桃冫| 亚洲电影免费| 欧美岛国激情| 日韩午夜中文字幕| 亚洲欧洲中文日韩久久av乱码| 蜜臀av在线播放一区二区三区 | 欧美在线免费视屏| 亚洲自拍啪啪| 国产一区二区日韩精品欧美精品| 欧美中文字幕不卡| 欧美伊久线香蕉线新在线| 国产伦理一区| 久久婷婷丁香| 一区二区精品国产| 久久精品国产欧美激情| 宅男66日本亚洲欧美视频| 先锋亚洲精品| 欧美诱惑福利视频| 狠狠色丁香婷婷综合| 毛片一区二区| 欧美精品日韩精品| 亚洲免费视频在线观看| 午夜精品国产更新| 一区二区三区在线免费视频 | 中文一区二区| 国产亚洲欧美激情| 欧美不卡一卡二卡免费版| 欧美高清在线视频| 亚洲综合精品| 久久精品日韩| 在线一区二区三区四区五区| 亚洲一区二区成人在线观看| 精品av久久707| 一区二区三区不卡视频在线观看 | 国产精品va| 久久久久久久久综合| 欧美va天堂va视频va在线| 亚洲午夜视频在线| 久久躁狠狠躁夜夜爽| 亚洲视频大全| 久久综合给合久久狠狠狠97色69| 这里只有精品视频| 欧美在线免费视屏| 亚洲一区二区在线免费观看| 久久久精品久久久久| 亚洲一区二区三区中文字幕| 久久精品一区二区国产| 亚洲天堂网站在线观看视频| 久久精视频免费在线久久完整在线看| 一区二区av在线| 久久婷婷国产麻豆91天堂| 亚洲在线免费视频| 麻豆精品一区二区av白丝在线| 欧美一区二区三区免费视频| 欧美激情综合| 欧美韩日一区| 一区二区视频免费在线观看| 亚洲视频一区二区| 99精品视频免费全部在线| 久久人91精品久久久久久不卡| 欧美一区二区三区在线观看视频| 欧美日韩国产另类不卡| 久久九九免费| 国产乱肥老妇国产一区二| 一本色道精品久久一区二区三区| 亚洲国产一区二区三区高清 | 亚洲国产精品v| 黄色免费成人| 欧美伊人久久| 久久手机免费观看| 国产亚洲一区二区三区| 亚洲免费一在线| 亚洲欧美日韩国产一区二区| 欧美日韩蜜桃| 日韩视频中文| 亚洲一区二区免费在线| 欧美日韩国产不卡在线看| 91久久久国产精品| 亚洲另类视频| 欧美区在线观看| 亚洲精品久久久久久一区二区| 伊人一区二区三区久久精品| 久久精品国产一区二区电影 | 久久午夜国产精品| 免费在线亚洲| 91久久精品国产91久久| 鲁大师影院一区二区三区| 欧美成人dvd在线视频| 亚洲免费观看| 亚洲第一在线视频| 久久国产精品久久久久久电车| 欧美怡红院视频| 国产亚洲毛片| 久久日韩粉嫩一区二区三区| 免费在线观看精品| 亚洲三级视频| 国产精品夜夜嗨| 最新亚洲一区| 免费欧美日韩| 亚洲精品小视频在线观看| 亚洲少妇自拍| 国产精品永久免费观看| 久久成人免费| 欧美国产精品一区| 99精品国产高清一区二区| 欧美视频在线观看 亚洲欧| 午夜一级久久| 欧美激情一区在线| 亚洲视频免费在线观看| 国产麻豆日韩| 模特精品裸拍一区| 亚洲午夜久久久久久久久电影院 | 一本色道久久综合狠狠躁的推荐| 亚洲欧美日韩视频一区| 国产一区三区三区| 欧美日韩国产在线| 欧美在线一区二区| 亚洲精品久久久久中文字幕欢迎你| 亚洲欧美成人一区二区在线电影| 国产一区在线视频| 欧美日韩成人精品| 久久久国产精品亚洲一区| 亚洲精选一区二区| 另类综合日韩欧美亚洲| 亚洲网站在线播放| 亚洲国产精品久久久久婷婷884 | 亚洲精品国产精品久久清纯直播 | 欧美三级视频在线观看| 久久黄色网页| 亚洲视频欧美视频| 亚洲第一天堂av| 欧美一区二区三区啪啪| 99国产精品久久久久久久久久 | 曰韩精品一区二区| 欧美视频在线不卡| 欧美精品一区二区久久婷婷| 欧美中文在线视频| 99精品免费视频| 亚洲国产va精品久久久不卡综合| 久久国产精品99国产精| 在线亚洲电影|