• <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>

            loop_in_codes

            低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

            MMO聊天服務器設計

            MMO中的聊天服務主要功能就是做客戶端之間的聊天內容轉發(fā)。但是聊天的形式有很多,例如私聊、同場景聊、隊伍內聊、工會內聊、全服務器聊、甚至臨 時組建房間聊。這些邏輯功能其實都是可以做在邏輯服務器上的,最多改改世界服務器,但是這樣完成功能的話,不免將聊天本身的邏輯與游戲邏輯關聯(lián)起來。我們 希望做得更上一層,將聊天服務本身脫離開來。但是獨立聊天服務還不夠,因為就算獨立出來了,也有可能在實現(xiàn)上與具體的游戲邏輯相關聯(lián)。所以,我們做了進一 步的抽象,想實現(xiàn)一個更為通用的聊天服務器。

            設計實現(xiàn)

            實體設計

            聊天這個過程,我們將其抽象為實體(entity)與實體間的對話。這個實體概念其實很寬泛。任何可接收聊天消息的都算做實體,例如單個玩家、一個 場景、一個隊伍、一個房間、一個工會、甚至整個服務器。這個思想其實就是支持整個聊天服務器設計的最根本思想。最開始,我將聊天服務器分為個體和組兩個概 念,其實這個抽象程度都太低,并且會導致實現(xiàn)上的復雜。相反,將整個系統(tǒng)完全使用實體這個概念來組裝,就簡單很多。當然,實體是有很多種類的,在處理接收 聊天消息這個動作時,其處理方式就不同。例如單個玩家實體僅做消息的發(fā)送,場景實體則是將消息發(fā)給場景內的所有玩家,隊伍實體就是將消息發(fā)給隊伍內的所有 玩家。從這一點來看,我們的實體種類其實并不多,因為場景、隊伍這些,都是組實體(group entity)。用C++來描述:

            class Entity {
            public:
                
            // send text to this entity
                virtual bool Send(Entity *sender, const std::string &text) = 0;

            protected:
                GUID m_id;
                
            int m_type;
            };

            class SockEntity : pubilc Entity {
            public:
                
            virtual bool Send(Entity *sender, const std::string &text) {
                    
            // find the map socket and send text to the socket
                    long socket = FindSocket(this);
                    Message msg(MSG_CS2E_SENDTEXT);
                    msg.Add(sender
            ->ID());
                    msg.Add(text);
                    msg.SendToSocket(socket);
                    
            return true;
                }
            };

            class GroupEntity : public Entity {
            public:
                
            virtual bool Send(Entity *sender, const std::string &text) {
                    
            for (std::list<Entity*>::const_iterator it = m_mems.begin(); it != m_mems.end(); ++it) {
                        (
            *it)->Send(sender, text);
                    }
                    
            return true;
                }
            private:
                std::list
            <Entity*> m_mems;
            };

            
            

            SockEntity用于表示物理上聊天服務器的客戶端,例如游戲客戶端。

            網(wǎng)絡拓撲

            實際上,除了轉發(fā)聊天內容外(Entity::Send),實體還有很多其他行為,例如最起碼的,創(chuàng)建組實體,往組實體里添加成員等。在設計上,組 實體的創(chuàng)建由邏輯服務器或者其他服務器來完成,目前游戲客戶端是沒有創(chuàng)建組實體的權限的(實現(xiàn)上我們還為實體添加了權限驗證機制)。在網(wǎng)絡拓撲上,聊天服 務器始終是作為服務器角色,而它的客戶端則包括游戲客戶端、邏輯服務器、甚至其他服務器,這樣聊天服務器在提供了固定的協(xié)議后,它就是完全獨立的,不依賴 任何其他組件:

                         CS
                      
            /  |  \
                     
            /   |   \
                    
            /    |    \
                   GC   GC   GS
            
            

            (CS: Chat Server, GC: Game Client, GS: Game Server)

            基于此,我們擴充了Entity的類體系:

            class ClientEntity : public SockEntity {

            private:
                GUID m_gsEntity; 
            // 標示該客戶端實體位于哪個邏輯服務器實體上
            };

            class GSEntity : public SockEntity {
            };

            消息協(xié)議

            聊天服務器的核心實現(xiàn),其實就是針對以上實體做操作。因此,聊天服務器的消息協(xié)議方面,也主要是針對這些實體的操作,包括:

            • 創(chuàng)建

              實體的創(chuàng)建很簡單,不同的實體其創(chuàng)建所需的參數(shù)都不一樣。例如客戶端實體創(chuàng)建時需要傳入一個邏輯服務器實體的ID,組實體的創(chuàng)建可以攜帶組成員實體列表。 為了處理權限和安全問題,在具體實現(xiàn)上,邏輯服務器實體的創(chuàng)建是由聊天服務器本地的配置決定,即聊天服務器啟動則根據(jù)配置創(chuàng)建好邏輯服務器實體;客戶端實 體是當角色進入邏輯服務器后,由服務器創(chuàng)建,客戶端無法創(chuàng)建實體。

            • 刪除

              實體的刪除為了處理方便,約定刪除請求必須由實體的創(chuàng)建者發(fā)起。因為從邏輯上將,某個模塊如果可以創(chuàng)建一個實體,那么其必然知道什么時候該刪除這個實體。

            • 修改

              修改指的是修改實體內部實現(xiàn)的一些屬性,例如組實體修改其組成員。這個操作是非常重要的。對于SockEntity而 言,修改意味著修改其連接狀態(tài),例如當邏輯服務器在聊天服務器上創(chuàng)建了客戶端實體后,實際上此時客戶端并沒有在網(wǎng)絡方面連接聊天服務器,此時這個Entity實 際上是不可用的,因為它無法用于發(fā)送消息。這個時候我們標志該實體的狀態(tài)為非連接狀態(tài)。當客戶端主動連接上聊天服務器后,客戶端就主動發(fā)起修改自己對應的 客戶端實體請求,該請求將自己的狀態(tài)修改為連接狀態(tài)。當客戶端關閉時,聊天服務器網(wǎng)絡層接收到連接斷開通知,該通知肯定是早于邏輯服務器發(fā)來的刪除實體通 知的,此時將該客戶端實體狀態(tài)修改為斷開狀態(tài),并在接收到邏輯服務器刪除實體通知時將其真正刪除。這里展示的這種狀態(tài)修改策略,實際上在整個系統(tǒng)中是非常 重要的。它用于指導網(wǎng)絡連接和上層邏輯之間的關系,因為整個聊天系統(tǒng)中,各個進程的狀態(tài)是不可預料的(隨時可能宕掉),當某個進程尤其是邏輯服務器宕掉 后,聊天服務器是得不到任何正常邏輯通知的,它只能得到網(wǎng)絡連接的通知。

            總結

            整個系統(tǒng)實現(xiàn)下來,實際上是非常簡單的,代碼量也很少。當然還有很多細節(jié)問題,例如聊天信息中攜帶物品信息,這涉及到異步預處理聊天內容,這里就不 方便細說了。

            原文地址: http://codemacro.com/2012/08/29/mmo-chat-server/
            written by Kevin Lynx  posted at http://codemacro.com

            posted on 2012-08-29 11:37 Kevin Lynx 閱讀(3588) 評論(2)  編輯 收藏 引用 所屬分類: game develop

            評論

            # re: MMO聊天服務器設計 2012-08-29 12:29 飯中淹

            感覺過于強調實體,反而讓概念顯得不清楚了,屬于過度抽象。
            從現(xiàn)實來講
            頻道和聊天者的概念會比較清晰一點。  回復  更多評論   

            # re: MMO聊天服務器設計 2012-08-30 21:26 畢達哥拉斯半圓

            同意樓上,不管什么實體,映射到Chat-Server上某個channel的就可以了,話說,我也想有個ChatServer做一些事情,不過目前的想法是基于Irc server/client改一改,感覺這樣比較簡單且快速一點。  回復  更多評論   

            久久久久久免费视频| 国产福利电影一区二区三区,免费久久久久久久精 | 伊人久久精品影院| 亚洲国产精品无码久久一线| 成人妇女免费播放久久久| 国产成人AV综合久久| 性做久久久久久久久老女人| 久久国产精品成人片免费| 97精品国产97久久久久久免费| 久久99这里只有精品国产| 久久96国产精品久久久| 久久亚洲AV无码精品色午夜| 国产精品久久久久久| 国产精品99久久久精品无码| 国内精品久久久久久久coent| 久久人人爽人人爽人人片av麻烦| 99久久精品毛片免费播放| 久久婷婷五月综合国产尤物app| 国产国产成人精品久久| 亚洲中文字幕无码一久久区| 久久99国产一区二区三区| 久久久老熟女一区二区三区| 久久中文字幕人妻熟av女| 欧美与黑人午夜性猛交久久久 | 区久久AAA片69亚洲| 国产精品久久国产精麻豆99网站| 18禁黄久久久AAA片| 欧美性猛交xxxx免费看久久久| 国产三级观看久久| 国产精品久久久久久久久| 久久久久免费看成人影片| 中文字幕日本人妻久久久免费| 久久久99精品成人片中文字幕 | 亚洲国产成人久久综合一| 久久国产精品无码HDAV| 久久狠狠高潮亚洲精品| 无码专区久久综合久中文字幕| 亚洲狠狠婷婷综合久久久久| 亚洲色婷婷综合久久| 久久精品中文騷妇女内射| 久久精品国产久精国产思思|