• <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>
            posts - 311, comments - 0, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            (搬運工)關于mangos多線程處理方式

            Posted on 2012-07-23 11:25 點點滴滴 閱讀(1129) 評論(0)  編輯 收藏 引用 所屬分類: 10 服務器
            由于目前的MANGOS只是針對個人單機用戶制作的,并非真正的服務器版。使用的是單線程的處理方式。
            關于mangos多線程處理方式

            聽說配置這個文件是管理線程的,不過不知道有沒有用!
            # 在多線程系統 使用線程MASK(只在Windows系統下使用)
            # 默認: 0 (操作系統來選擇)
            # 舉例: 數字
            UseProcessors = 0

            目前的mangos上了幾十人后,只要有組隊的組團的就會卡,奇怪CPU占用也不高。請教了大大之后明白原來是mangos自身的瓶頸問題。

            CK說:
            由于目前的MANGOS只是針對個人單機用戶制作的,并非真正的服務器版。使用的是單線程的處理方式。這個由代碼就可以看出,整個World(包括人物,怪等)都是靠World.cpp里的update函數發起掉用的。而他是使用單線程的方式,從頭遍歷所有的玩家,一個一個按照次序的來進行獲取封包,并處理然后發送。這也就是為什么,當你打開MANGOS這個服務端,竟然CPU占用很少的原因。
            在網上,我也看到過有人打算用多開區(EXE)來達到玩家分流,也只是治表不治本的方法。按照MANGOS的框架總體上來說人數達到100其實是一個上限值再上去的話,可能情況就是PING值雖然不高,但還是覺得卡。因為玩家封包沒有及時處理,而停留在“等待處理”中。卡怪,卡魔法這樣的情況很容易產生。特別當有一個PING值非常高的玩家,在SESSION排隊列表里比你靠前時,這種情況最容易發生。

            CK給出的代碼:
            在World.cpp文件里,做一個線程函數來代替
            update函數里的

            CODE:

            for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
            {
            next = itr;
            next++;

            if(!itr->second)
            continue;

            if(!itr->second->Update(diff))
            {
            delete itr->second;
            m_sessions.erase(itr);
            }
            }
            [url=javascript:][Copy to clipboard][/url]

            以上代碼就是我剛才說的,從頭遍歷所有玩家并依次調用,所有玩家session的update函數。以下是修正建立自己的線程
            CODE:

            DWORD World::_UpdateThread(LPVOID lp)
            {
            ThreadParm *parm = (ThreadParm *)lp;
            World *pworld = (World *)parm->world;
            HANDLE m_hSingle = NULL;
            while (true)
            {
            SessionMap sessions = pworld->GetSessions();
            SessionMap::iterator itr = NULL;
            SessionMap::iterator next = NULL;

            for (itr = sessions.begin(), next; itr != sessions.end(); itr = next)
            {
            next = itr;
            next++;

            if(itr == NULL || !itr->second || itr->second->GetWorking())
            continue;

            m_hSingle = OpenEvent(EVENT_ALL_ACCESS,true,"worldsession"); //這里必須對所操作資源進行同步處理,否則將會出現線程之間資源訪問的沖突。一個線程處理一個玩家,其他線程直接跳轉到后面的列隊
            if (m_hSingle == NULL)
            {
            m_hSingle = CreateEvent(NULL, FALSE, TRUE, "worldsession");
            }
            if (WaitForSingleObject(m_hSingle, 10000) == WAIT_TIMEOUT)//我把超時設置為10秒,以防死鎖
            {
            SetEvent(m_hSingle);
            m_hSingle = CreateEvent(NULL, FALSE, TRUE, "worldsession");
            }
            itr->second->SetWorking(true);
            SetEvent(m_hSingle); //記得別忘了把鎖打開,否則這個玩家之后所有的封包操作將被忽略。
            if (!itr->second->Update(time(NULL)))
            {
            pworld->RemoveErrorSession(itr->second->GetAccountId());
            }
            else
            {
            itr->second->SetWorking(false);
            }
            }
            Sleep(100); //線程間隔時間我設置為0.1秒
            }
            return 0;
            }
            [url=javascript:][Copy to clipboard][/url]

            接下來就是如何去開啟線程進行處理了,在world.cpp里有個SetInitialWorldSettings函數,這個是初始化World里面所有數據的總入口。我們可以把線程啟動放那里。
            先在mangosd.conf文件里設置一串
            CODE:
            WorldSessionThread = 3
            [url=javascript:][Copy to clipboard][/url]
            設置3個啟動線程
            接下去就是在SetInitialWorldSettings里修改了
            CODE:

            ....
            sLog.outString( "Loading Loot Tables..." );
            LoadLootTables();
            //在這里添加我們的線程函數
            for (int i = 0; i diff = i;
            t->world = this;
            ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_UpdateThread,(LPVOID)t,0,&tid);
            }
            [url=javascript:][Copy to clipboard][/url]
            GetIntDefault函數第一個我就不解釋了,第二個值是表示默認值,比如你配置文件里沒設置WorldSessionThread = 3這條語句的話,默認就是2個線程

            這樣一來,我們的MANGOS服務端在處理能力上,將得到很大的提升


            龍苑的林碧給出的提示:
            thread.cpp

            #include <stdio.h>
            #ifdef _WIN32
            #include "socket_include.h"
            #else
            #include <unistd.h>
            #endif

            #include "Thread.h"

            #ifndef __GNUC__

            // UQ1: warning C4311: 'type cast' : pointer truncation
            #pragma warning(disable:4311)

            #endif

            Thread::Thread(bool release)
            :m_thread(0)
            ,m_running(true)
            ,m_release(false)
            {
            #ifdef _WIN32
            m_thread = ::CreateThread(NULL, 0, StartThread, this, 0, &m_dwThreadId);
            #else
            pthread_attr_t attr;

            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
            if (pthread_create(&m_thread,&attr,StartThread,this) == -1)
            {
            perror("Thread: create failed");
            SetRunning(false);
            }
            // pthread_attr_destroy(&attr);
            #endif
            m_release = release;
            }


            Thread::~Thread()
            {
            // while (m_running || m_thread)
            if (m_running)
            {
            SetRunning(false);
            SetRelease(true);

            #ifdef _WIN32
            struct timeval tv;
            tv.tv_sec = 0;
            tv.tv_usec = 100000;
            select(0,NULL,NULL,NULL,&tv);
            ::CloseHandle(m_thread);
            #else
            sleep(1);
            #endif
            }
            }


            threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz)
            {
            Thread *pclThread = (Thread *)zz;

            while (pclThread -> m_running && !pclThread -> m_release)
            {
            #ifdef _WIN32
            struct timeval tv;
            tv.tv_sec = 0;
            tv.tv_usec = 100000;
            select(0,NULL,NULL,NULL,&tv);
            #else
            sleep(1);
            #endif
            }
            if (pclThread -> m_running)
            {
            pclThread -> Run();
            }
            pclThread -> SetRunning(false); // if return
            return (threadfunc_t)zz;
            }


            bool Thread::IsRunning()
            {
            return m_running;
            }


            void Thread::SetRunning(bool x)
            {
            m_running = x;
            }


            bool Thread::IsReleased()
            {
            return m_release;
            }


            void Thread::SetRelease(bool x)
            {
            m_release = x;
            }
            久久久久一级精品亚洲国产成人综合AV区 | 99久久国产宗和精品1上映| 国産精品久久久久久久| 岛国搬运www久久| 久久伊人精品一区二区三区| 精品久久久久成人码免费动漫| 人妻无码中文久久久久专区| 久久久精品免费国产四虎| 日韩久久无码免费毛片软件| 久久香蕉国产线看观看精品yw| 欧美一区二区精品久久| 久久精品国产亚洲αv忘忧草| 久久久无码一区二区三区| 久久夜色精品国产www| 久久国产欧美日韩精品| 一级做a爰片久久毛片毛片| avtt天堂网久久精品| 亚洲午夜精品久久久久久浪潮 | 国产成人精品免费久久久久| 99精品国产免费久久久久久下载| 777米奇久久最新地址| 国产精品久久久久久久久久影院 | 97久久精品无码一区二区| 久久久久久久免费视频| 国产成人精品久久亚洲高清不卡 | 一本久久a久久精品亚洲| 亚洲综合精品香蕉久久网97 | 久久精品成人欧美大片| 午夜精品久久影院蜜桃| 久久国产成人| 久久久久国产日韩精品网站| 97超级碰碰碰碰久久久久| 久久久久国产精品| 久久婷婷国产麻豆91天堂| 久久精品99久久香蕉国产色戒 | 午夜精品久久久久久久| 中文字幕亚洲综合久久菠萝蜜| 热综合一本伊人久久精品| 亚洲&#228;v永久无码精品天堂久久 | 久久婷婷是五月综合色狠狠| 国产精品99久久久精品无码|