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

               C++ 技術(shù)中心

               :: 首頁(yè) :: 聯(lián)系 ::  :: 管理
              160 Posts :: 0 Stories :: 87 Comments :: 0 Trackbacks

            公告

            鄭重聲明:本BLOG所發(fā)表的原創(chuàng)文章,作者保留一切權(quán)利。必須經(jīng)過(guò)作者本人同意后方可轉(zhuǎn)載,并注名作者(天空)和出處(CppBlog.com)。作者Email:coder@luckcoder.com

            留言簿(27)

            搜索

            •  

            最新隨筆

            最新評(píng)論

            評(píng)論排行榜

            網(wǎng)絡(luò)游戲服務(wù)器端一些注意事項(xiàng)

             

            一:IOCP和Epoll之間的異同。
            異:
            1:IOCP是WINDOWS系統(tǒng)下使用。Epoll是Linux系統(tǒng)下使用。
            2:IOCP是IO操作完畢之后,通過(guò)Get函數(shù)獲得一個(gè)完成的事件通知。
            Epoll是當(dāng)你希望進(jìn)行一個(gè)IO操作時(shí),向Epoll查詢是否可讀或者可寫(xiě),若處于可讀或可寫(xiě)狀態(tài)后,Epoll會(huì)通過(guò)epoll_wait進(jìn)行通知。
            3:IOCP封裝了異步的消息事件的通知機(jī)制,同時(shí)封裝了部分IO操作。但Epoll僅僅封裝了一個(gè)異步事件的通知機(jī)制,并不負(fù)責(zé)IO讀寫(xiě)操作。Epoll保持了事件通知和IO操作間的獨(dú)立性,更加簡(jiǎn)單靈活。
            4: 基于上面的描述,我們可以知道Epoll不負(fù)責(zé)IO操作,所以它只告訴你當(dāng)前可讀可寫(xiě)了,并且將協(xié)議讀寫(xiě)緩沖填充,由用戶去讀寫(xiě)控制,此時(shí)我們可以做出額 外的許多操作。IOCP則直接將IO通道里的讀寫(xiě)操作都做完了才通知用戶,當(dāng)IO通道里發(fā)生了堵塞等狀況我們是無(wú)法控制的。

            同:
            1:它們都是異步的事件驅(qū)動(dòng)的網(wǎng)絡(luò)模型。
            2:它們都可以向底層進(jìn)行指針數(shù)據(jù)傳遞,當(dāng)返回事件時(shí),除可通知事件類型外,還可以通知事件相關(guān)數(shù)據(jù)。

            二:描述一下IOCP:
            扯遠(yuǎn)點(diǎn)。首先傳統(tǒng)服務(wù)器的網(wǎng)絡(luò)IO流程如下:
            接到一個(gè)客戶端連接->創(chuàng)建一個(gè)線程負(fù)責(zé)這個(gè)連接的IO操作->持續(xù)對(duì)新線程進(jìn)行數(shù)據(jù)處理->全部數(shù)據(jù)處理完畢->終止線程。
            但是這樣的設(shè)計(jì)代價(jià)是:
            1:每個(gè)連接創(chuàng)建一個(gè)線程,將導(dǎo)致過(guò)多的線程。
            2:維護(hù)線程所消耗的堆棧內(nèi)存過(guò)大。
            3:操作系統(tǒng)創(chuàng)建和銷毀線程過(guò)大。
            4:線程之間切換的上下文代價(jià)過(guò)大。
            此時(shí)我們可以考慮使用線程池解決其中3和4的問(wèn)題。這種傳統(tǒng)的服務(wù)器網(wǎng)絡(luò)結(jié)構(gòu)稱之為會(huì)話模型。
            后來(lái)我們?yōu)榉乐勾罅烤€程的維護(hù),創(chuàng)建了I/O模型,它被希望要求可以:
            1:允許一個(gè)線程在不同時(shí)刻給多個(gè)客戶端進(jìn)行服務(wù)。
            2:允許一個(gè)客戶端在不同時(shí)間被多個(gè)線程服務(wù)。
            這樣做的話,我們的線程則會(huì)大幅度減少,這就要求以下兩點(diǎn):
            1:客戶端狀態(tài)的分離,之前會(huì)話模式我們可以通過(guò)線程狀態(tài)得知客戶端狀態(tài),但現(xiàn)在客戶端狀態(tài)要通過(guò)其他方式獲取。
            2:I/O請(qǐng)求的分離。一個(gè)線程不再服務(wù)于一個(gè)客戶端會(huì)話,則要求客戶端對(duì)這個(gè)線程提交I/O處理請(qǐng)求。
            那么就產(chǎn)生了這樣一個(gè)模式,分為兩部分:
            1:會(huì)話狀態(tài)管理模塊。它負(fù)責(zé)接收到一個(gè)客戶端連接,就創(chuàng)建一個(gè)會(huì)話狀態(tài)。
            2:當(dāng)會(huì)話狀態(tài)發(fā)生改變,例如斷掉連接,接收到網(wǎng)絡(luò)消息,就發(fā)送一個(gè)I/O請(qǐng)求給 I/O工作模塊進(jìn)行處理。
            3:I/O工作模塊接收到一個(gè)I/O請(qǐng)求后,從線程池里喚醒一個(gè)工作線程,讓該工作線程處理這個(gè)I/O請(qǐng)求,處理完畢后,該工作線程繼續(xù)掛起。
            上面的做法,則將網(wǎng)絡(luò)連接 和I/O工作線程分離為兩個(gè)部分,相互通訊僅依靠 I/O請(qǐng)求。
            此時(shí)可知有以下一些建議:
            1:在進(jìn)行I/O請(qǐng)求處理的工作線程是被喚醒的工作線程,一個(gè)CPU對(duì)應(yīng)一個(gè)的話,可以最大化利用CPU。所以 活躍線程的個(gè)數(shù) 建議等于 硬件CPU個(gè)數(shù)。
            2:工作線程我們開(kāi)始創(chuàng)建了線程池,免除創(chuàng)建和銷毀線程的代價(jià)。因?yàn)榫€程是對(duì)I/O進(jìn)行操作的,且一一對(duì)應(yīng),那么當(dāng)I/O全部并行時(shí),工作線程必須滿足I/O并行操作需求,所以 線程池內(nèi)最大工作線程個(gè)數(shù) 建議大于或者等于 I/O并行個(gè)數(shù)。
            3:但是我們可知CPU個(gè)數(shù)又限制了活躍的線程個(gè)數(shù),那么線程池過(guò)大意義很低,所以按常規(guī)建議 線程池大小 等于 CPU個(gè)數(shù)*2 左右為佳。例如,8核服務(wù)器建議創(chuàng)建16個(gè)工作線程的線程池。
            上面描述的依然是I/O模型并非IOCP,那么IOCP是什么呢,全稱 IO完成端口。
            它是一種WIN32的網(wǎng)絡(luò)I/O模型,既包括了網(wǎng)絡(luò)連接部分,也負(fù)責(zé)了部分的I/O操作功能,用于方便我們控制有并發(fā)性的網(wǎng)絡(luò)I/O操作。它有如下特點(diǎn):
            1:它是一個(gè)WIN32內(nèi)核對(duì)象,所以無(wú)法運(yùn)行于Linux.
            2:它自己負(fù)責(zé)維護(hù)了工作線程池,同時(shí)也負(fù)責(zé)了I/O通道的內(nèi)存池。
            3:它自己實(shí)現(xiàn)了線程的管理以及I/O請(qǐng)求通知,最小化的做到了線程的上下文切換。
            4:它自己實(shí)現(xiàn)了線程的優(yōu)化調(diào)度,提高了CPU和內(nèi)存緩沖的使用率。
            使用IOCP的基本步驟很簡(jiǎn)單:
            1:創(chuàng)建IOCP對(duì)象,由它負(fù)責(zé)管理多個(gè)Socket和I/O請(qǐng)求。CreateIoCompletionPort需要將IOCP對(duì)象和IOCP句柄綁定。
            2:創(chuàng)建一個(gè)工作線程池,以便Socket發(fā)送I/O請(qǐng)求給IOCP對(duì)象后,由這些工作線程進(jìn)行I/O操作。注意,創(chuàng)建這些線程的時(shí)候,將這些線程綁定到IOCP上。
            3:創(chuàng)建一個(gè)監(jiān)聽(tīng)的socket。
            4:輪詢,當(dāng)接收到了新的連接后,將socket和完成端口進(jìn)行關(guān)聯(lián)并且投遞給IOCP一個(gè)I/O請(qǐng)求。注意:將Socket和IOCP進(jìn)行關(guān)聯(lián)的函數(shù)和創(chuàng)建IOCP的函數(shù)一樣,都是CreateIoCompletionPort,不過(guò)注意傳參必然是不同的。
            5:因?yàn)槭钱惒降模覀兛梢匀プ銎渌却齀OCP將I/O操作完成會(huì)回饋我們一個(gè)消息,我們?cè)龠M(jìn)行處理。
            其中需要知道的是:I/O請(qǐng)求被放在一個(gè)I/O請(qǐng)求隊(duì)列里面,對(duì),是隊(duì)列,LIFO機(jī)制。當(dāng)一個(gè)設(shè)備處理完I/O請(qǐng)求后,將會(huì)將這個(gè)完成后的I/O請(qǐng)求丟回IOCP的I/O完成隊(duì)列。
            我們應(yīng)用程序則需要在GetQueuedCompletionStatus去詢問(wèn)IOCP,該I/O請(qǐng)求是否完成。
            其中有一些特殊的事情要說(shuō)明一下,我們有時(shí)有需要人工的去投遞一些I/O請(qǐng)求,則需要使用PostQueuedCompletionStatus函數(shù)向IOCP投遞一個(gè)I/O請(qǐng)求到它的請(qǐng)求隊(duì)列中。


            三:網(wǎng)絡(luò)游戲服務(wù)器注意事項(xiàng),優(yōu)化措施
            1:IO操作是最大的性能消耗點(diǎn),注意優(yōu)化余地很大。
            2:算法數(shù)據(jù)結(jié)構(gòu)。排序?qū)ぢ匪惴ǖ膬?yōu)化。list,vector,hashmap的選擇。大數(shù)據(jù)尋址,不要考慮遍歷,注意考慮hash.
            3:內(nèi)存管理。重載new/delete,內(nèi)存池,對(duì)象池的處理。
            4:數(shù)據(jù)的提前準(zhǔn)備和即時(shí)計(jì)算。
            5:CPU方面的統(tǒng)計(jì)監(jiān)視。邏輯幀計(jì)數(shù)(應(yīng)當(dāng)50ms以內(nèi))。
            6:預(yù)分配池減少切換和調(diào)度,預(yù)處理的線程池和連接池等。
            7:基與消息隊(duì)列的統(tǒng)計(jì)和信息監(jiān)視框架。
            8:CPU消耗排名:第一AOI同步,第二網(wǎng)絡(luò)發(fā)包I/O操作,第三技能/BUFF判定計(jì)算處理,第四定時(shí)器的頻率。
            9:內(nèi)存泄露檢測(cè),內(nèi)存訪問(wèn)越界警惕,內(nèi)存碎片的回收。
            10:內(nèi)存消耗排名:第一玩家對(duì)象包括其物品,第二網(wǎng)絡(luò)數(shù)據(jù)緩沖。
            11:注意32位和64位的內(nèi)存容錯(cuò)。
            12:減少不必要的分包發(fā)送。
            13:減少重復(fù)包和重拷貝包的代價(jià)。
            14:建議分緊急包(立刻發(fā)送)和非緊急包(定時(shí)輪訓(xùn)發(fā)送)。
            15:帶寬消耗排名:第一移動(dòng)位置同步,第二對(duì)象加載,第三登陸突發(fā)包,第四狀態(tài)機(jī)定時(shí)器消息。
            16:客戶端可做部分預(yù)判斷機(jī)制,部分操作盡量分包發(fā)送。
            17:大量玩家聚集時(shí),部分非緊急包進(jìn)行丟棄。
            18:注意數(shù)據(jù)庫(kù)單表內(nèi)key數(shù)量。
            19:活躍用戶和非活躍用戶的分割存取處理。
            20:控制玩家操作對(duì)數(shù)據(jù)庫(kù)的操作頻率。
            21:注意使用共享內(nèi)存等方式對(duì)數(shù)據(jù)進(jìn)行安全備份存儲(chǔ)。
            22:注意安全策略,對(duì)內(nèi)網(wǎng)進(jìn)行IP檢查,對(duì)日志進(jìn)行記錄,任意兩環(huán)點(diǎn)內(nèi)均使用加密算法會(huì)更佳。
            23:實(shí)時(shí)注意對(duì)網(wǎng)關(guān),數(shù)據(jù)庫(kù)等接口進(jìn)行監(jiān)察控制。
            24:定時(shí)器應(yīng)當(dāng)存儲(chǔ)一個(gè)隊(duì)列,而非單向定位。
            25:九宮格數(shù)據(jù)同步時(shí),不需要直接進(jìn)行九宮格的同步,對(duì)角色加一個(gè)AOI,基于圓方碰撞原理,拋棄不必要的格信息,可大幅節(jié)省。
            26:客戶端做部分的預(yù)測(cè)機(jī)制,服務(wù)器檢測(cè)時(shí)注意時(shí)間戳問(wèn)題。
            27:定期心跳包,檢查死鏈接是必要的。
            28:為了實(shí)現(xiàn)更加負(fù)責(zé)多種類的AI,AI尋路獨(dú)立服務(wù)器設(shè)計(jì)已經(jīng)是必須的了。其次需要考慮的是聊天,同步。
            29:服務(wù)器內(nèi)網(wǎng)間可以考慮使用UDP。
            30:注意所有內(nèi)存池,對(duì)象池等的動(dòng)態(tài)擴(kuò)張分配。

            1:以內(nèi)存換取CPU的理念。
            2:NPC不死理念。(只會(huì)disable)
            3:動(dòng)態(tài)擴(kuò)展理念,負(fù)載均衡理念。
            4:客戶端不可信理念。
            5:指針數(shù)據(jù),消息均不可信理念。

            posted on 2012-08-07 22:34 C++技術(shù)中心 閱讀(1075) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 游戲開(kāi)發(fā)

            Feedback

            # re: 網(wǎng)游開(kāi)發(fā)注意事項(xiàng) 2012-09-07 00:00 Jcilz
            有價(jià)值的分享,簡(jiǎn)潔明了  回復(fù)  更多評(píng)論
              

            久久性精品| 人人狠狠综合久久亚洲88| 欧美精品一本久久男人的天堂| 2021最新久久久视精品爱| 青青热久久国产久精品| 久久久人妻精品无码一区| 久久香蕉国产线看观看猫咪?v| 久久久久婷婷| 成人综合久久精品色婷婷| 久久天天躁狠狠躁夜夜躁2014| 久久久久久伊人高潮影院| 亚洲色欲久久久综合网东京热| 久久亚洲AV成人无码| 色欲久久久天天天综合网 | 性做久久久久久久久| 午夜精品久久影院蜜桃| 亚洲另类欧美综合久久图片区| 久久乐国产综合亚洲精品| 久久久久亚洲国产| 国产精品无码久久久久久| 久久亚洲高清观看| 久久亚洲国产精品123区| 精品国产乱码久久久久久呢| 久久久精品人妻一区二区三区四| 99国产精品久久| 无码乱码观看精品久久| 亚洲AV日韩精品久久久久久| 久久久青草青青亚洲国产免观| 久久国产免费直播| 亚洲精品tv久久久久久久久| 婷婷久久综合九色综合98| 亚洲欧美精品一区久久中文字幕| 久久久一本精品99久久精品88| 久久国产成人| 久久精品国产99久久无毒不卡| 久久久久亚洲AV无码专区桃色 | 国产免费久久久久久无码| 成人综合久久精品色婷婷| 99久久婷婷国产综合精品草原 | 国产精品视频久久| 久久精品视屏|