freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

游戲服務器架構(文件)

2024-10-13 20:02 上一頁面

下一頁面
 

【正文】 程,那外掛制作者總有辦法知道我們的加密過程,所以,這個方法仍不夠安全。噢,不要管那個王小云的什么論文,如果我真有那么好的運氣,早中500w了,還用在這考慮該死的服務器設計嗎?似乎是一個很完美的方案,外掛制作者再也偷不到我們的密碼了。很幸運的是,偉大的數(shù)學字們早就為我們準備好了很多優(yōu)秀的這類算法,而且經(jīng)理論和實踐都證明他們也確實是足夠安全的。不過其代碼實現(xiàn)步驟倒是并不復雜,mangos中的代碼也還算清晰,我們也不再贅述。登錄服將從大區(qū)服上獲取到的游戲世界列表發(fā)給已驗證通過的客戶端即可。服務器公共組件實現(xiàn)mangos的游戲主循環(huán)當閱讀一項工程的源碼時,我們大概會選擇從main函數(shù)開始,而當開始一項新的工程時,第一個寫下的函數(shù)大多也是main。mangos的登錄服是一個單線程的結構,雖然在數(shù)據(jù)庫連接中可以開啟一個獨立的線程,但這個線程也只是對無返回結果的執(zhí)行類SQL做緩沖,而對需要有返回結果的查詢類SQL還是在主邏輯線程中阻塞調(diào)用的。很簡單的結構,也比較容易理解。另外,在服務器實現(xiàn)上,網(wǎng)絡IO與邏輯處理一般會放在不同的線程中,以免耗時較長的IO過程阻塞住了需要立即反應的游戲邏輯。正如我們曾討論過的,為了游戲主邏輯循環(huán)的流暢運行,所有比較耗時的IO操作都會分享到單獨的線程中去做,如網(wǎng)絡IO,數(shù)據(jù)庫IO和日志IO等。這個循環(huán)將一直持續(xù),直到收到一個通知服務器關閉的消息包。}這里就有一個問題需要探討了,在getMessage()的時候,我們應該去哪里取消息?前面我們考慮過,至少會有三個消息來源,而我們還討論過,這些消息源的IO操作都是在獨立的線程中進行的,我們這里的主線程不應該直接去那幾處消息源進行阻塞式的IO操作。Message* getMessage()。我們所能想到的最簡單的消息隊列可能就是使用stl的list來實現(xiàn)了,即消息隊列內(nèi)部維護一個list和一個互斥鎖,putMessage時將message加入到隊列尾,getMessage時從隊列頭取一個message返回,同時在getMessage和putMessage之前都要求先獲取鎖資源。提供一個隊列容器,里面有多個隊列,每個隊列都可固定存放一定數(shù)量的消息。這里為每個隊列設了個最大消息數(shù),看來好像是打算只有當IO線程寫滿隊列時才會將其放回到容器中換另一個隊列。兩個隊列,一個給邏輯線程讀,一個給IO線程用來寫,當邏輯線程讀完隊列后會將自己的隊列與IO線程的隊列相調(diào)換。兩種方案都是很優(yōu)秀的優(yōu)化方案,但也都是有其適用范圍的。頻繁的內(nèi)存分配不但增加了系統(tǒng)開銷,更使得內(nèi)存碎片不斷增多,非常不利于我們的服務器長期穩(wěn)定運行。如果追上了怎么辦?那就是沒有數(shù)據(jù)可讀了,先等會兒唄,等跑的人向前跑幾步了再追,總不能讓游戲沒得玩了吧。也就是,大家都得遵守規(guī)定,追的人不能從桌子上跨過去,跑的人當然也不允許反過來跑。在解包及解密完成后,我們會將這個數(shù)據(jù)包復制到邏輯線程消息隊列中,如果我們只使用一個隊列,那這里也將會是個環(huán)形緩沖區(qū),IO線程往里寫,邏輯線程在后面讀,互相追逐。服務器公共組件實現(xiàn)發(fā)包的方式前面一直都在說接收數(shù)據(jù)時的處理方法,我們應該用專門的IO線程,接收到完整的消息包后加入到主線程的消息隊列,但是主線程如何發(fā)送數(shù)據(jù)還沒有探討過??紤]數(shù)據(jù)緩存的話,那這里這可以有兩種實現(xiàn)方式了,一是為每個玩家準備一個緩沖區(qū),另外就是只有一個全局的緩沖區(qū),要發(fā)送的數(shù)據(jù)加入到全局緩沖區(qū)的時候同時要指明這個數(shù)據(jù)是發(fā)到哪個socket的。有關該優(yōu)化的說明在云風描述其連接服務器實現(xiàn)的blog文章中也有講到,有興趣的可以去閱讀一下。bool(AuthSocket::*handler)(void)。而這個狀態(tài)標識的改變是在運行時進行的,確切的說是在收到某個消息并正確處理完后改變的。由于這里的兩個狀態(tài)標識只區(qū)分出了兩種狀態(tài),所以,我們僅需要兩個獨立的類,用以表示兩種狀態(tài)即可。void Process(Message* msg)= 0。}。具體的實現(xiàn)細節(jié)就不做過多描述了。BR正如同在設計模式中所描述的,所有的模式都是已有問題的另一種解決方案,也就是說這并不是唯一的解決方案。本節(jié)內(nèi)容欠考慮,希望大家多給點意見。這樣,與QT類似,對于事件我們可以重定義其處理方法,甚至過濾掉某些事件使其不被處理,但對于信號我們只是收到了一個通知,有些類似于Observe模式中的觀察者,當收到更新通知時,我們只能更新自己的狀態(tài),對剛剛發(fā)生的事件我不已不能做任何影響。簡單點說,就是我們可以為事件定義過濾器,使得事件可以被過濾。另外還有一個需要我們關注的問題是事件和信號處理時的優(yōu)先級問題。最后需要我們考慮的是事件和信號的處理方式。我們需要注意的一個很重要的問題是會不會引起循環(huán)調(diào)用。再談登錄服的實現(xiàn)離我們的登錄服實現(xiàn)已經(jīng)太遠了,先拉回來一下。LoginServer處理玩家的登錄及世界服選擇請求。剛開始時,世界列表是空的,慢慢的,世界服會一個個加入進來,而這里如果有世界服當機,他會顯示為離線,不會從列表中刪除。類似的,如果DNSServer也可以讓LoginServer自己去注冊,這樣在臨時LoginServer時就不需要去改動DNSServer的配置文件了。由于世界列表并不常變化,所以LoginServer沒有必要每次發(fā)送世界列表時都到WorldServerMgr上去取,LoginServer完全可以自己維護一個列表,當WorldServerMgr上的列表發(fā)生變化時,WorldServerMgr會主動通知所有的LoginServer也更新一下自己的列表。先從狀態(tài)機開始,前面也說過了,登錄服上的連接會有兩種狀態(tài),一是帳號密碼驗證狀態(tài),一是服務器列表選擇狀態(tài),其實還有另外一個狀態(tài)我們未曾討論過,因為它與我們的登錄過程并無多大關系,這就是升級包發(fā)送狀態(tài)。升級狀態(tài)其實就是文件傳輸過程,文件發(fā)送完畢后通知客戶端開始執(zhí)行升級文件并關閉連接。當客戶端選擇了一個世界之后該怎么辦?wow的做法是,當客戶端選擇一個游戲世界時,客戶端會主動去連接該世界服的IP和PORT,然后進入這個游戲世界。打個比方,有個不自覺的玩家不遵守游戲規(guī)則,沒有去驗證帳號密碼就直接跑去連接世界服了,就如同一個不自覺的乘客沒有換登機牌就直接跑到登機口一樣。方法很簡單,去找給他登機牌的那個檢票員問一下,這張牌是不是他發(fā)的不就得了。這兩種方案的本質并無差別,只是看你愿意將負載放在哪里。一個可行的方案是,讓任意時刻只有一個地方保存一個客戶端的session key,這個地方可能是客戶端當前正連接著的服務器,也可以是它正要去連接的服務器。當然了,為了session key的安全,所有的服務器在收到一個新的session key后都會為其設一個有效期,在有效期過后還沒來認證的,則該session key會被自動刪除。不管是怎樣一種方式,了解了其過程,代碼實現(xiàn)都是比較簡單的,我們就不再贅述了第四篇:游戲架構設計淺談游戲策劃的前期工作班級:09數(shù)字媒體技術姓名:廖偉民學號:090804006摘要:游戲制作所涉及的知識領域極其廣泛,其中就單其游戲策劃這一塊就涉及到三大內(nèi)容:前期的準備工作、中期的制作工作、后期的宣傳工作。其實每一個游戲的策劃都要經(jīng)歷很多步驟和過程,就游戲策劃的前期準備工作當中就包含了對技術、經(jīng)濟、人力資源這三點的可行性分析,市場調(diào)研,確定工作計劃以及撰寫策劃草案這四個步驟,下面我將對其一一經(jīng)行分析。在這篇文章當中我將針對游戲策劃當中的前期準備進行說明,并發(fā)表自己的看法。但是,很顯然的,wow并沒有采用這種方案,因為客戶端在選擇世界服時并沒有向服務器發(fā)送要求確認的消息。如果客戶端這時想要去某個游戲世界,那么他必須先通知當前連接的LoginServer要去的服務器地址,LoginServer將session key安全轉移給目標服務器,轉移的意思是要確保目標服務器收到了session key,本地保存的要刪除掉。所以,我們也可以試著考慮一種新的方案,一種不需要去全區(qū)唯一一個入口查詢的方案。那么,LoginServer將這個key存到數(shù)據(jù)庫中,讓網(wǎng)關服自己去數(shù)據(jù)庫驗證?似乎也是個可行的方案。一樣的處理過程,我們的登錄服在驗明客戶端身份后,也會發(fā)給客戶端一個登機牌,這個登機牌還有一個學名,叫做session key。這是一個很必要的設計,保證了我們在因意外情況連接不上世界服或者發(fā)現(xiàn)世界服正在排隊而想換另外一個試試時不會需要重新進行密碼驗證。如果客戶端一直連接著,則該狀態(tài)會以每5秒一次的頻率不停刷新列表給客戶端,當然是否值得這樣做還是有待商榷。密碼驗證的過程使用了SRP6協(xié)議,具體過程就不多做描述,每個游戲使用的方式也都不大一樣。WorldServerMgr實現(xiàn)所要考慮的內(nèi)容就這些,我們再來看看LoginServer,這才是我們今天要重點討論的對象。這里可以用一個心跳包來實現(xiàn)其狀態(tài)的檢測,如果WorldServer的連接斷開或者在規(guī)定時間內(nèi)未收到心跳包,則將其狀態(tài)更新為離線。從上面的過程描述中,我們很容易想到利用一個臨時的列表來保存世界服信息,這也是我們增加WorldServerMgr服務器的目的所在。在mangos的代碼中,我們注意到登錄服是從數(shù)據(jù)庫中取的世界列表,而在wow官方服務器中,我們卻會注意到,這個世界服列表并不是一開始就固定,而是動態(tài)生成的。GateWay/WorldServer GateWay/WodlServer LoginServer LoginServer DNSServer WorldServerMgr | | | | | | | | internet | clients其中DNSServer負責帶負載均衡的域名解析服務,返回LoginServer的IP地址給客戶端。在上面的文字中就同時出現(xiàn)了消息、事件和信號三個相近的概念,而在實際處理中,經(jīng)常發(fā)現(xiàn)三者不知道如何界定的情況,實際的情況比我在這里描述的要混亂的多。而信號的處理方式有些不同,信號處理是立即回調(diào)的,也就是一個信號產(chǎn)生后,他上面所注冊的所有槽都會立即被回調(diào)。對于信號的處理則比較簡單,默認是沒有順序的,如果需要明確的順序,可以在信號注冊時顯示地指明槽的位置。關于事件和信號機制的實現(xiàn),網(wǎng)絡上的開源訓也比較多,比如FastDelegate,sigslot,boost::signal等,其中sigslot還被Google采用,在libjingle的代碼中我們可以看到他是如何被使用的。但有一項區(qū)別在于,事件處理函數(shù)的返回值是有意義的,我們要根據(jù)這個返回值來確定是否還要繼續(xù)事件的處理,比如在QT中,事件處理函數(shù)如果返回true,則這個事件處理已完成,QApplication會接著處理下一個事件,而如果返回false,那么事件分派函數(shù)會繼續(xù)向上尋找下一個可以處理該事件的注冊方法。比如在QT應用程序中,用戶的一次鼠標點擊會產(chǎn)生一個鼠標點擊事件加入到事件隊列中,當處理此事件時可能會導致某個按鈕控件產(chǎn)生一個clicked()信號。比如在游戲服務器上玩家的狀態(tài)管理,還有在實現(xiàn)NPC人工智能時的各種狀態(tài)管理,這些就留作以后的專題吧。當我們在進行狀態(tài)轉換時,可能會需要將一些現(xiàn)場數(shù)據(jù)從老狀態(tài)對象轉移到新狀態(tài)對象,這需要在定義接口時做一下考慮。當要進行狀態(tài)轉換時,調(diào)用MachineBase的ChangeState()方法,顯示地告訴狀態(tài)機管理類自己要轉到哪一個狀態(tài)。狀態(tài)機基類接口:MachineBase{void ChangeState(StateBase* state)= 0。稍作整理,大概的代碼會類似這樣:狀態(tài)基類接口:StateBase{void Enter()= 0。描述的情況與我們這里所要處理的情況是如此的相似,也許我們可以試一試。該結構體定義了每個消息碼的處理函數(shù)及需要的狀態(tài)標識,只有當前狀態(tài)滿足要求時才會調(diào)用指定的處理函數(shù),否則這個消息碼的出現(xiàn)是不合法的。首先還是從mangos的代碼開始看起,我們注意到登錄服在處理客戶端發(fā)來的消息時用到了這樣一個結構體:struct AuthHandler{eAuthCmd cmd。采用第二種方式還可以附帶一個優(yōu)化方案。但是直接send調(diào)用有時候有會存在一些問題,比如遇到系統(tǒng)的發(fā)送緩沖區(qū)滿而阻塞住的情況,或者只發(fā)送了一部分數(shù)據(jù)的情況也時有發(fā)生。因為我們對同一個隊列不再會出現(xiàn)同時讀和寫的情況,每個隊列在寫滿后交給邏輯線程去讀,邏輯線程讀完后清空隊列再交給IO線程去寫,一段固定大小的緩沖區(qū)即可。環(huán)形緩沖區(qū)是一項很好的技術,不用頻繁的分配內(nèi)存,而且在大多數(shù)情況下,內(nèi)存的反復使用也使得我們能用更少的內(nèi)存塊做更多的事。要是一直這么反著追,估計您就只能換一個跑的更快的追逐者了,要不這游戲還真沒法玩下去。但是對于這種按照嚴格的先進先出順序處理的,塊大小并不算小的,而且塊大小也并不統(tǒng)一的內(nèi)存分配情況來說,更多使用的是一種叫做環(huán)形緩沖區(qū)的方案,mangos的網(wǎng)絡代碼中也有這么一個東西,其原理也是比較簡單的。arthur的方案很好的解決了上一個方案遺留的問題,但因為只有一個寫隊列,所以當想要提供多個IO線程時,線程間互斥地寫入數(shù)據(jù)可能會增大競爭的機會,當然,如果只有一個IO線程那將是非常完美的。雖然看起來鎖的調(diào)用次數(shù)是比前一種方案要多很多,但實際上大部分鎖調(diào)用都是不會引起阻塞的,只有在邏輯線程調(diào)換隊列的那一瞬間可能會使得某個線程阻塞一下。Ghost Cheng在他的描述中沒有講到如何解決這種問題,但我們可以先來看看另一個方案。而邏輯線程取消息時是從隊列容器中取一個有消息的隊列來讀取,處理完后清空隊列再放回到容器中。其最大的問題在頻繁的鎖競爭上。有關消息隊列的實現(xiàn)和線程間消息的傳遞在ACE中有比較完全的代碼實現(xiàn)及描述,還有一些使用示例,是個很好的參考。好比是,我這里提供了一個倉庫,有很多的供貨商,他們有貨要給我的時候只需要交到倉庫,然后我再到倉庫去取就是了,這個倉庫也就是消息隊列。我們可以用一段簡單的偽碼來描述這個循環(huán)過程:while(Message* msg = getMessage()){if(msg為服務器關閉消息)break。另外對于大多數(shù)服務器程序來說,在運行時都是作為精靈進程或服務進程的,所以我們并不需要服務器能夠
點擊復制文檔內(nèi)容
環(huán)評公示相關推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1