關於遊戲網絡設計的問題

1、追溯

去gameloft筆試,有一個題目是說:程序員

叫你去設計一個FPS(第一人稱射擊遊戲),你是要用TCP呢仍是要用UDP,說明理由 。服務器

2、學習

這是兩篇網上找到的文章,寫很是不錯。網絡

當時筆試的時候本身沒想到這麼全,但大概想法都是一致的,摘錄下來再學習一下。架構

 

1.網絡遊戲程序員須知 UDP vs TCP

做者:rellikt@gmail.com框架

首發連接:http://blog.csdn.net/rellikt/archive/2010/08/21/5829020.aspxtcp

 

這篇教程讓咱們就從最基本的網絡數據收發開始談起吧。其實這部分纔是網絡程序員應該作的最基礎最簡單的部分,可是這部分若是想要作好相對來講仍是頗有技巧和困難的。並且若是這部分你沒作好,在多人對戰類遊戲中它帶來的影響是極其惡劣的。學習

你可能據說過端口這個概念,也可能知道TCP和UDP這兩個概念。在作網絡開發的的時候,咱們首先要作的就是選擇合適的協議。究竟是TCP,仍是UDP,或者是二者混合來用呢?這是一個問題。測試

其實來講,你的選擇應該和你須要作的遊戲類型相關。因此首先若是你是作網絡遊戲開發的,從如今起,我默認你對一些知名的網絡遊戲,好比COD,Quake, Unreal, CS已經很熟悉了。優化

既然咱們要談網絡遊戲的協議選擇,咱們就先得對各類協議來個深刻的瞭解,這樣到底應該選擇那種協議也就不言而喻了。.net

TPC/IP

TCP

TCP解釋爲傳輸控制協議,IP解釋爲網絡協議。他們合起來就完成了你平常網絡的大部分工做,好比寫email,看網頁等。

假如你曾經使用過TCP,那麼你確定知道TCP是可靠協議。即你先在兩臺機器間創建鏈接,而後你再在兩臺機器上開始傳輸數據,傳輸的過程和文件讀寫很像。你在一頭寫,在另一頭讀而已。

TCP協議是可靠並且有序的,這個意味着TCP負責保證你的數據能夠完整並且有序的傳輸到另一端。TCP是經過流的方式來傳輸數據的,這就意味這TCP會負責把你的數據切分,打包,而後具體傳輸。

最後記住,TCP傳輸其實就和讀寫文件同樣簡單。  by rellikt

IP

IP協議的抽象簡單概念與IP協議底層傳輸的複雜真實實現造成鮮明對比。

這裏不須要任何鏈接的概念,數據包從一個電腦傳輸到另一個電腦,就像你在上課的教室裏面傳紙條同樣。你只要給出一個最終的目的地,包天然會傳到那個終端,固然中間還會通過好多層的路由遞送。

你徹底不能肯定本身的包最終會不會到達目的地,只能但願它到達。若是你想知道包最終是否到達,那你就必須讓接收者收到之後作出回覆。

事實上,整個過程可能還要更復雜一些,因爲沒有一臺機器可以預知包能夠最快到達的完整路由途徑,因此有時候IP協議會將包複製多份發出,這些包會走不一樣的路由,所以他們通常也會在不一樣的時刻到達。

你必須瞭解因特網路由問題的設計原則是自主組織路徑,自主修復路徑。因此當你思考問題的底層是如何實現時那是至關帶勁的,固然你能夠在相關的教科書上找到你想要的內容或者wiki。

UDP

咱們已經有一種能夠像寫文件同樣穩定傳輸數據的方法了,若是咱們還想要一種能夠自由的收發包的方法,咱們能夠怎麼作呢?

這裏咱們能夠用到UDP。UDP解釋爲「user datagram protocol」(用戶自定義數據協議)。它和TCP相似也是創建在IP協議上的,不過他相比起TCP來在IP協議上只作了薄薄的一層協議。

咱們可使用UDP協議直接對指定的IP和端口發包,好比 1.0.0.127:21(本機的FTP端口)。這個包會從發送者本身路由到接收者手中,固然也有可能半路丟失掉。

在接收端,咱們只要偵聽相關端口就能夠了,當有包從任何電腦發來的時候(這裏沒有鏈接的概念),咱們在獲得包的數據的同時,也獲得了包的發送者的IP和端口數據,發送包的大小。

UDP是不穩定可靠的傳輸協議,事實上大部分的包是會被送達的,可是你通常會有1%到5%的丟包率。甚至你會發現有段時間,你連一個包都收不到。路由路徑上的那些機器出了點啥問題,誰知道呢?

有時候收包的順序和發包的順序也是不一樣的,可能你發包的時候是1,2,3,4,5的順序發。收到的包就變成1,3,4,5,2的順序了。固然大部分時候這個順序是不會亂的。可是這個誰都不敢打保票。

UDP只能保證你一件事,那就是包的完整性。你若是發一個256bytes的包,那麼對方收到的確定也是一個256bytes的包。他不會只收到半個包之類的。固然這其實也是UDP惟一能保證你的事情。其餘事情都要靠你本身去訂製。 by rellikt

TCP vs UDP

咱們如今要作一個選擇了。開發遊戲究竟是用UDP好呢?仍是用TCP好呢?

首先咱們連列一下他們的有缺點:

TCP:

1. 基於鏈接的協議。

2. 可靠性和數據包的序列性是有保證的。

3. 自動爲你的數據封包。

4. 確保包的流量不會超出你的網絡連接的負載上限。

5. 簡單易用,你只須要像寫文件同樣去讀寫就萬事大吉了。

UDP:

1. 沒有鏈接的概念,若是你想要,本身去實現去。

2. 沒有關於可靠性和包序列性的保證,包可能會丟失,重複,亂序。

3. 你必須本身去封包。

4. 你必須本身確保本身的數據包不會流量過大從而致使超過連接負載上限。

5. 你必須本身處理包的丟失,重複,亂序的狀況,若是你不想他們對你的程序形成麻煩,必需要本身實現代碼來作出應對。

這樣一比,咱們顯然應該用那個TCP協議了。它完成了全部咱們想要的特性,實在是太完美了,不是嗎?by rellikt

TCP的真實工做狀況

TCP和UDP都是基於IP協議的,可是他們的本質確實大相徑庭的。UDP和它底層的IP協議相似,TCP卻將不少東西進行了抽象,它使你在使用它的時候感受就像讀寫一個文件同樣,事實上他對你隱藏了不少複雜功能的實現細節。

它究竟是如何實現這些細節的呢?

首先,TCP是流性質的協議,你將數據一個比特一個比特的寫入流,而後TCP來確保他們會最終到底目的地。咱們必須明確:TCP協議是基於IP協議的,IP協議是基於數據包的。這裏TCP實際上是把咱們的數據流在底層進行了打包。事實上有一些TCP協議中的代碼就是把咱們的數據流進行排隊,而後依次寫入包中,當包寫入了足夠多的數據之後,它就會把包發走。

這裏就會致使一些問題,由於你不能控制底層的打包和傳輸,因此當很小的用戶輸入數據寫入數據流的時候,TCP可能會湊滿必定量的數據(好比100bytes),而後再打包發送。這樣的話,在實時性上面就會不好,由於也許你會須要這些包越快到達越好。這些小延遲也許就會大大的影響你的遊戲性。

TCP中其實有一個TCP_NODELAY的選項,使用這個選項之後,你的數據就會跳過TCP的隊列打包過程,直接發送。

可是即便你使用的這個技術,你在多人網絡遊戲中仍是會遇到不小的問題。

這些問題源自於TCP實現可靠傳輸的機制。by rellikt

TCP是如何實現可靠傳輸的

基本上來講,TCP將數據流中的數據作成封包,而後將他們經過不可靠的IP協議發送,而後在接收端重組這些包成爲數據流。

可是當一個包丟失的時候TCP會作些什麼呢?當包重複和亂序的時候TCP又作了些什麼呢?

這裏我不想作太深刻的介紹,有興趣的讀者能夠在wiki上找到他們須要的細節。大體來講,TCP發現丟包的時候,會要求發送者重發,重複的包會被丟棄,亂序包會被排序,事實上他就是這麼保證傳輸的可靠性的。

這裏的丟包處理對遊戲來講就很糟糕了。TCP中,若是你發現丟包了,必須等待發送者進行重發,在重發的包到來之前,即便有新包來,你也只能讓他們在隊列裏等着,不能讀取,這個等待的時間大概是ping值的1.5倍,若是重發的包再次丟失的話那就是3倍的時間。假設你的ping值是125ms,丟包一次就會延遲200ms左右,若是連續丟包就是400ms,這樣的狀況在大多數即時類遊戲中是不能忍受的。

爲什麼你不能選用TCP做爲遊戲開發的網絡協議

經過上面的論述,其實已經很明白了。在注重即時性的遊戲中,對於延遲的要求是很苛刻的,咱們能夠丟包,可是若是咱們收到了比丟掉的包更新的包的話,咱們徹底能夠無論丟掉的包。咱們只關注當前數據。

這裏咱們來假設一個最簡單的多人遊戲的模型。好比一個FPS遊戲,你在客戶段每次將輸入的數據(好比前進,跳躍,開火)發送到服務器端,而後服務器端將玩家當前的位置和狀況發回給客戶端來作顯示。

在這個最簡單的模型中,只要有一個包丟失了,全部的東西都必須停下來等包的重發,任何操做都得停掉,你不能移動也不能射擊。等到這個包到達的時候,你總算能繼續操做了。可是可能你會發現還有一堆等等待重發的包在排隊,因而你只好繼續等,並且可能你收到的這個重發包對遊戲來講已經失去時效性,徹底沒意義了。這樣的遊戲你能忍嗎?

不幸的是你對TCP協議的這個行爲徹底無能爲力。這是TCP協議的本性,就是它保證了TCP協議的可靠性的。

咱們不須要這樣沒法訂製的可靠性協議。咱們須要本身進行訂製丟包時的處理原則。這也是咱們在開發遊戲時,避免使用TCP協議的緣由。

是否能夠混合使用TCP和UDP協議呢?

上面的結論中,咱們能夠明確知道,一些相似玩家操做,玩家位置的時效性相關數據,咱們必須不能使用TCP協議。可是有些數據確是必須保證可靠性的,那咱們是否可使用TCP協議來作同步呢?

這個想法是很好的,咱們能夠在玩家操做等即時性很強的數據上使用UDP協議,在玩家AI,數據加載,玩家對話等序列性很強的數據上使用TCP。若是你願意的話,甚至能夠爲不一樣的AI建立不一樣的TCP鏈接,以避免一個AI的丟包會影響的另一個AI的即時性。

看上去這是一個不錯的思路。可是這僅僅是看上去而已。因爲TCP和UDP都是基於IP協議的,事實上他們在底層會互相干擾。關於干擾的細節我這裏就不詳細論述了,想了解的讀者能夠閱讀這篇文章。 by rellikt

結論

個人建議是在遊戲中僅僅使用UDP做爲網絡協議,即便要使用TCP也是本身在UDP的基礎上實現一種類TCP的協議。這也是現代遊戲中流行的網絡架構。

接下來的文章中我會介紹如何實現這套架構。下一篇會講的比較實際點,講關於如何使用UDP收發包。盡請期待。 by rellikt

 

2.FPS遊戲服務器設計的一些想法(FROM 高總)

連接:http://blog.csdn.net/sunguangran/article/details/6064256

      FPS遊戲,至今我尚未真正設計過。從去年到盛大、今年到金山,感謝校長、錦州,讓我有不少機會和公司內外的團隊溝通和互相學習,加上本身有qqtang server的設計經驗,對FPS遊戲慢慢有些瞭解,通過不斷的討論,對其中的細節也逐步有些深刻。由於沒有完整設計過FPS遊戲,因此不少想法多是有很大誤差的,只是總結一下這1年多以來的心得。

1、玩家的遊戲數據轉發採用 UDP+應用層確認? 仍是 UDP+TCP ?

      qqtang遊戲數據轉發採用的後者,全部遊戲數據(移動+撿道具+泡泡爆炸等)都經過UDP來轉發,可是對於撿道具、泡泡爆炸等遊戲關鍵數據是還會用tcp再轉發一次。這樣設計的緣由是若是隻有UDP(沒有確認,不能重傳)轉發,UDP包丟失的話,就會致使遊戲邏輯混亂,好比有個道具在界面上,不能撿,可是又阻礙人物行走;或者泡泡永不爆炸等狀況。這些關鍵數據若是採用TCP轉發就保證可靠性,而對於人物移動包,部分丟失不會影響遊戲邏輯,因此只用UDP轉發,也減小了流量。

反恐行動1的遊戲包只有UDP轉發,今年3月份和他們溝通的時候我一直都不是很明白他們是怎麼保證可靠性的,後來纔想清楚。它的轉發邏輯應該是移動包等(容許必定丟失率的包)經過UDP轉發,並且沒有確認機制;遊戲關鍵數據包(好比中彈、換槍等)也是經過UDP來轉發的,可是這些包在應用層有確認和重發機制來保證數據的可靠傳輸。

到底哪一種方式更好了,能夠參考下qq server和qqgame server:

      2003年qq server採用的是公司本身設計的ftcp協議,就是基於UDP、在應用層實現可靠傳輸的協議。它主要是解決當時select模型的接入量和效率問題,當時qqgame也採用了ftcp協議來提升qqgame server的負載。但後來發現它不適合在遊戲server上使用。緣由是qqgame有20K以上的大包,ftcp協議要求咱們進行拆分紅n多小包發送,每一個小包丟失都會致使整個大包的接收失敗。採用ftcp協議能提升了接入量但單個用戶的服務質量降低。最後沒有辦法咱們仍是用了select模型(半年後改成epoll模型,大大提升了接入量)。

反恐的模型(UDP+UDP應用層確認)和qqtang server(UDP+TCP),這兩個模型,我比較建議用前者。

        1)fps遊戲過程中沒有大包出現。

        2)統一採用udp,設計簡單、邏輯一致。

        3)流量更小,FPS遊戲對網絡延遲要求很高,UDP的丟包率不高,全部關鍵包都轉發浪費很多流量。

2、P2P模型? 仍是 C/S模型?

相似於qqtang、泡泡堂、泡泡卡丁車或者cf等遊戲幾年前咱們設計的思路都採用的是P2P方式。記得2004年的時候,帶寬的成本好像是一個月30W/G。如今的成本好像只有1/6-1/3,將來成本還會持續降低。

我以前統計qqtang的P2P打通率大概是70%,大約有70%的流量是經過P2P方式傳輸的,下降了運營商成本。可是整個互聯網大環境的趨勢對於P2P是不提倡的,另外重要的是P2P的方式致使程序設計很複雜,對於團隊特別是創業團隊是一個比較大的瓶頸,還會致使服務器的防外掛機制設計困難,玩家和玩家遊戲數據的互通讓server很難參與到其中來控制。

        qqtang是p2p模型,cf、反恐都是c/s模型,從我的經驗看,除非在p2p上頗有經驗,不然採用cs模型可能更合適。

3、大廳服務器和遊戲服務器的分離

        qqtang server的大廳和遊戲是處於一個物理和邏輯服務器。crossfire的大廳服務器是集中在IDC機房,遊戲邏輯服務器分佈在CDN中。玩家開房進入遊戲狀態後會登陸到遊戲服務器上進行遊戲,這種就近接入的方式在crossfire的運營上很是成功,很好的解決了FPS對網絡延遲要求高的問題。

反恐行動1在服務器的分佈上就沒有像crossfire那樣作,絕大部分玩家玩得仍是不錯,有少許的玩家反應有點卡。還好反恐行動2會解決這個問題,反恐行動2各方面都作了很大的優化,相信會有更佳的表現。

        FPS遊戲由於對網絡要求很是高,因此採用了分地域、就近接入的方式,這點和mmog有很大的不一樣,也是fps運營質量的保證。

4、玩家狀態是即時轉發仍是狀態同步

錦州以前設計的活力風暴時採用後者方案,每50ms把玩家的狀態廣播一次,玩家在50ms內發生的2次行爲好比換過2把槍,只會把後面的狀態記錄下來。這會致使

         1)錄像回放很差作,由於沒有完整的行爲過程,

         2)50ms的狀態轉發不會很精確,延時不肯定,並且同步線程和主邏輯線程也有同步問題會無故增長延時。

         3)流量增長,每次狀態同步會把一些沒有變化的數據同步。 
         qqtang採用的是前者,程序設計相對複雜一點;但消息延遲更低,記錄了遊戲世界的事件邏輯。

5、服務器行走模擬?

服務器行走模擬的基礎是採用cs模型,錦州以前採用unreal解決方案進行過測試,若是服務器作行走模擬能夠很好的解決反外掛的問題,可是開銷實在太大,物理碰撞之類的運算量太大;相似的嘗試也在qqtang作過,我接手qqtang的時候還有服務器行走模擬的代碼,最後發現cpu開銷太大取消了。

服務器硬件的持續發展也許會讓服務器行走模擬成爲可行,若是可行,fps遊戲的反外掛自然將造成了一個自然的屏障。

6、玩家傷害判斷和防外掛

因爲服務器計算碰撞的代價太大,因此玩家傷害等行爲除了服務器作必定的校驗外,主要是靠玩家之間互相的驗證來實現的。在網絡要求高的遊戲中,通常咱們都是以服務好網速更好的玩家爲原則的,因此fps遊戲防外掛是個比較艱鉅的任務,就像以前的qqtang同樣,客戶端承擔了太多的運算,同時又要保證好的用戶感,就須要遊戲邏輯中增長更多的防外掛的考慮。qqtang主要採用的是掃描特徵碼、動態代碼執行等方案。

        unreal在fps已經造成了一套相對完整的解決方案,反恐1中已經獲得驗證,開發門檻低,效率還能夠,也許將來的fps遊戲能夠採用現成的方案,開發者只須要完成主體框架和遊戲內細節邏輯。

沒有完整開發過一款fps遊戲,這些都是一些想法總結而

相關文章
相關標籤/搜索