自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

游戲服務(wù)器:到底使用UDP還是TCP

開發(fā) 前端
一般來說你會(huì)聽到人們這樣說:“除非你正在寫一個(gè)動(dòng)作類游戲,否則你就用TCP吧” 或者是 “你能夠在MMO游戲中用TCP,因?yàn)槟ЙF世界就用的TCP!”

 在編寫網(wǎng)絡(luò)游戲的時(shí)候,到底使用UDP還是TCP的問題遲早都要面對(duì)。

一般來說你會(huì)聽到人們這樣說:“除非你正在寫一個(gè)動(dòng)作類游戲,否則你就用TCP吧” 或者是 “你能夠在MMO游戲中用TCP,因?yàn)槟ЙF世界就用的TCP!”

遺憾的是,這些觀點(diǎn)都沒有反映這個(gè)問題的復(fù)雜性。

背景

首先,說明一下,我之前主要是用TCP進(jìn)行網(wǎng)絡(luò)編程。我曾為一個(gè)流行的在線紙牌游戲編寫服務(wù)器了好幾年,在高峰期我們的每臺(tái)服務(wù)器能夠承受4000到10000個(gè)連接(同一臺(tái)物理機(jī)器上有多個(gè)服務(wù)器進(jìn)程在跑)都沒有問題。在我來看,TCP是一種安全而且常見的選擇。

盡管如此,我們最新的項(xiàng)目卻是使用UDP協(xié)議,而且我們的項(xiàng)目無法通過任何方式在TCP下工作。事實(shí)上,項(xiàng)目一開始使用的TCP,但是后來發(fā)現(xiàn)我們使用TCP無法達(dá)到我們需求的連接數(shù)量時(shí),我們只能換成UDP了。

在使用中TCP表現(xiàn)怎么樣呢

從原理上,TCP的優(yōu)勢(shì)有:

  • 簡(jiǎn)單直接的長(zhǎng)連接
  • 可靠的信息傳輸
  • 數(shù)據(jù)包的大小沒有限制

任何一個(gè)和TCP打過交道的人都知道,要實(shí)現(xiàn)一個(gè)穩(wěn)定的TCP網(wǎng)絡(luò)連接,需要處理各種隱藏的坑,比如斷線檢測(cè)、慢速客戶端響應(yīng)阻塞數(shù)據(jù)包,對(duì)開放連接的各種dos攻擊,阻塞和非阻塞IO模型等等。

除了上面列出的這些問題外,一個(gè)好的TCP模塊確實(shí)不好編碼實(shí)現(xiàn)。

但是,TCP最糟糕的特性是它對(duì)阻塞的控制。一般來說,TCP假定丟包是由于網(wǎng)絡(luò)帶寬不夠造成的,所以發(fā)生這種情況的時(shí)候,TCP就會(huì)減少發(fā)包速度。

在3G或WiFi下,一個(gè)數(shù)據(jù)包丟失了,你希望的是立馬重發(fā)這個(gè)數(shù)據(jù)包,然而TCP的阻塞機(jī)制卻完全是采用相反的方式來處理!

而且沒有任何辦法能夠繞過這個(gè)機(jī)制,因?yàn)檫@是TCP協(xié)議構(gòu)建的基礎(chǔ)。這就是為什么在3G或者WiFi環(huán)境下,ping值能夠上升到1000多毫秒的原因。

為什么不用UDP

UDP相對(duì)TCP來說既簡(jiǎn)單又困難。

舉個(gè)例子來說,UDP是基于數(shù)據(jù)包構(gòu)建,這意味著在某些方面需要你完全顛覆在TCP下的觀念。UDP只使用一個(gè)socket進(jìn)行通信,不像TCP需要為每一個(gè)客戶端建立一個(gè)socket連接。這些都是UDP非常不錯(cuò)的地方。

但是,大多數(shù)情況下你需要的僅僅是一些連接的概念罷了,一些基本的包序功能,以及所謂的連接可靠性。可惜的是,這些功能UDP都沒有辦法簡(jiǎn)單的提供給你,而你使用TCP卻都可以免費(fèi)得到。

這也是人們?yōu)槭裁唇?jīng)常推薦TCP的原因。在用TCP的時(shí)候你可以不考慮這些問題,直到你需要同步連接的數(shù)量級(jí)達(dá)到500以上的時(shí)候。

所以,是的,UDP沒有提供所有的解決方法,但是就像你看到的那樣,這也正是UDP好用的地方。在某種意義上來說,TCP對(duì)UDP就好比是Hibernate和手寫SQL的區(qū)別。

使用TCP失敗的地方

人們經(jīng)常給你建議,讓你去使用TCP,比如“TCP跟UDP一樣快”或者“游戲X用TCP如此成功,所以TCP當(dāng)然是首選”,然而,他們完全沒有理解為什么在那個(gè)特定的游戲中TCP是有效的,為什么UDP不按照順序發(fā)送數(shù)據(jù)包呢?

那么為什么魔獸世界采用TCP呢?首先我們需要解釋這個(gè)問題。這個(gè)問題其實(shí)是“為什么魔獸世界有的時(shí)候1000毫秒以上的延遲還能夠運(yùn)行?”這是TCP的性質(zhì)決定的,在發(fā)生丟包的時(shí)候,會(huì)產(chǎn)生巨大的延遲,因?yàn)門CP首先會(huì)去檢測(cè)哪些包發(fā)生了丟失,然后重發(fā)所有丟失的包,直到他們都被接收到。

可靠的UDP也是有延遲的,但是由于它是在UDP的基礎(chǔ)之上建立的通信協(xié)議,所以可以通過多種方式來減少延遲,不像TCP,所有的東西都要依賴于TCP協(xié)議本身而無法被更改。

就這一點(diǎn)來講,一些人要開始提到Nagle算法了,實(shí)際上它是你在實(shí)現(xiàn)任意一個(gè)對(duì)延遲敏感的TCP模型時(shí)首先需要禁止使用的。

那么魔獸世界以及其他的一些游戲是怎么處理延遲問題的呢?

方法也很簡(jiǎn)單,他們能夠隱藏掉延遲帶來的影響。

在魔獸世界中,玩家和玩家是無法碰撞的:因?yàn)檫@類碰撞是無法通過一些預(yù)測(cè)來處理的,但是玩家和環(huán)境之間的碰撞卻是可以通過預(yù)測(cè)來處理的,所以這里使用TCP是沒有問題的。

我們來看一下魔獸世界的戰(zhàn)斗就會(huì)發(fā)現(xiàn),玩家的攻擊指令發(fā)送給服務(wù)器的操作是放在比如“attack_entity(entity_id)”或者”cast_spell(entity_id, spell_id)“的接口中來做的,換句話說,瞄準(zhǔn)操作是獨(dú)立于進(jìn)行的。如此一來,一些類似發(fā)起攻擊動(dòng)作和釋放技能特效就能夠在沒有收到服務(wù)器確認(rèn)的情況下就直接執(zhí)行,比如展現(xiàn)冰凍技能的效果就可以在服務(wù)器沒有返回?cái)?shù)據(jù)前在客戶端就做出來。

客戶端直接開始進(jìn)行計(jì)算而不等待服務(wù)端確認(rèn)是一種典型的隱藏延遲的技術(shù)。

幾年前,我為一個(gè)叫“Five Card Jazz”的紙牌游戲編寫過客戶端。它使用的是http協(xié)議,它比直接的TCP協(xié)議連接的延遲更加嚴(yán)重。

我們用簡(jiǎn)單的紙牌繪制和抽牌的動(dòng)畫來掩蓋延遲的問題,所以延遲的問題只在非常糟糕的連接下才會(huì)被看出來。這種方法也非常的典型:發(fā)送請(qǐng)求的同時(shí)開始播放牌桌的動(dòng)畫,一直播放翻動(dòng)最后一張牌直到接收到了服務(wù)端傳回來的數(shù)據(jù)為止。魔獸世界的戰(zhàn)斗特效就是使用類似的原理。

這也意味著,我們到底是使用TCP還是UDP取決于我們能否隱藏延遲。

TCP在什么時(shí)候失效

一個(gè)采用TCP的游戲必須能夠處理好突發(fā)的延遲問題(紙牌客戶端就很典型,對(duì)突發(fā)性的一秒的延遲,玩家也不會(huì)產(chǎn)生什么抱怨)或者是擁有緩解延遲問題的好方法。

但是如果你運(yùn)行的是一個(gè)無法使用任何減緩延遲措施的游戲呢?玩家對(duì)玩家的動(dòng)作類游戲通常就屬于這個(gè)范疇,但是這也不僅僅限于動(dòng)作類游戲。

舉個(gè)例子:

我目前正在寫一個(gè)多人游戲(War Arcana)。

一種常見的操作是,你快速的移動(dòng)你的角色通過一張充滿戰(zhàn)爭(zhēng)迷霧的世界地圖,但是一旦你探索過,迷霧就會(huì)被打開。

為了確保游戲的規(guī)則,防止玩家作弊,服務(wù)器只能顯示玩家當(dāng)前位置附近的信息。這意味著不像魔獸世界,玩家無法在沒有得到服務(wù)器響應(yīng)的情況下,做出完整的動(dòng)作。和Five Card Jazz相比,我們即使允許500毫秒的延遲,也已經(jīng)非常困難了。

在實(shí)現(xiàn)了游戲的原型后,在局域網(wǎng)內(nèi)一切都進(jìn)行的非常順利,但當(dāng)我們?cè)赪iFi環(huán)境下測(cè)試時(shí),操作會(huì)間歇性的卡起來或者延遲高起來。寫了一些測(cè)試程序之后發(fā)現(xiàn),WiFi環(huán)境下偶爾會(huì)發(fā)生丟包行為,每當(dāng)發(fā)生丟包的時(shí)候,服務(wù)器的響應(yīng)速度就從100-150毫秒上升到1000-2000毫秒。

沒有任何辦法可以繞過TCP的這個(gè)設(shè)置來避開這個(gè)問題。

我們替換了TCP的代碼,用了自定義的可靠的UDP來實(shí)現(xiàn),把大量的丟包產(chǎn)生的延遲降到了僅僅只有50毫秒,甚至比以前TCP不丟包的情況一個(gè)來回的延遲還要小。當(dāng)然,這只可能建立在UDP之上,這樣我們才對(duì)可靠性擁有完全的掌控力。

困惑:可靠的UDP只是TCP的一種簡(jiǎn)單的實(shí)現(xiàn)?

你有沒有聽過這種說法:“可靠的UDP就像TCP一樣,所以還是用TCP吧”。

問題是這種說法是錯(cuò)誤的。可靠的UDP一點(diǎn)也不像TCP,要去實(shí)現(xiàn)一個(gè)特殊的阻塞控制。事實(shí)上,這也是你使用可靠UDP代替TCP的最大的原因,避免TCP的阻塞控制。

另一個(gè)重點(diǎn)是可靠的UDP的可靠性是如何保證的。這里有很多種方法去實(shí)現(xiàn)。我非常喜歡Quake3網(wǎng)絡(luò)庫代碼里的一些想法,它們也激發(fā)了我在War Arcana中使用UDP協(xié)議。

你也可以使用許多支持可靠通信的UDP庫,當(dāng)然,這樣在可靠性方面,相比自己手動(dòng)實(shí)現(xiàn)全部的代碼而言,可能會(huì)更加通用而失去了一些性能優(yōu)勢(shì)。

底線

那么到底是用UDP還是TCP呢?

如果是由客戶端間歇性的發(fā)起無狀態(tài)的查詢,并且偶爾發(fā)生延遲是可以容忍,那么使用HTTP/HTTPS吧。

如果客戶端和服務(wù)器都可以獨(dú)立發(fā)包,但是偶爾發(fā)生延遲可以容忍(比如:在線的紙牌游戲,許多MMO類的游戲),那么使用TCP長(zhǎng)連接吧。

如果客戶端和服務(wù)器都可以獨(dú)立發(fā)包,而且無法忍受延遲(比如:大多數(shù)的多人動(dòng)作類游戲,一些MMO類游戲),那么使用UDP吧。

這些也應(yīng)該考慮在內(nèi):你的MMO客戶端也許首先使用HTTP去獲取上一次的更新內(nèi)容,然后使用UDP跟游戲服務(wù)器進(jìn)行連接。

永遠(yuǎn)不要害怕去使用最佳的工具來解決問題。

原文鏈接: 1024 MONKEYS   翻譯: 伯樂在線 菜鳥浮出水

譯文鏈接: http://blog.jobbole.com/64638/

責(zé)任編輯:林師授 來源: 伯樂在線
相關(guān)推薦

2019-09-16 15:30:51

2016-08-09 19:36:48

2018-06-04 10:30:47

游戲服務(wù)器框架

2017-07-19 08:30:31

2019-02-20 13:57:48

游戲服務(wù)器框架

2020-03-02 17:49:40

大型游戲服務(wù)器

2019-09-10 09:40:11

游戲服務(wù)器框架

2017-07-20 10:35:51

2018-09-19 09:17:13

2017-07-19 16:17:53

2020-08-31 19:19:27

TCPUDP視屏面試

2016-01-08 10:24:32

Docker容器容器技術(shù)

2018-05-18 10:22:39

沖突游戲服務(wù)器

2018-11-28 09:53:50

游戲服務(wù)器線程

2013-03-07 10:08:04

模擬城市游戲服務(wù)器服務(wù)器忙

2010-06-13 09:31:45

WindowsLinux服務(wù)器操作系統(tǒng)

2018-12-17 10:59:50

游戲服務(wù)器結(jié)構(gòu)

2009-02-10 15:35:00

網(wǎng)絡(luò)游戲服務(wù)器網(wǎng)絡(luò)游戲

2014-12-22 13:59:05

FireflyGFirefly框架

2019-08-01 15:25:17

Http服務(wù)器協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)