關於TCP UDP各適用場景

2021-09-26 01:49:59 字數 3233 閱讀 4735

tcp解釋為傳輸控制協議,ip解釋為網路協議。他們合起來就完成了你日常網路的大部分工作,比如寫email,看網頁等。

假如你曾經使用過tcp,那麼你肯定知道tcp是可靠協議。即你先在兩台機器間建立連線,然後你再在兩台機器上開始傳輸資料,傳輸的過程和檔案讀寫很像。你在一頭寫,在另外一頭讀而已。

tcp協議是可靠而且有序的,這個意味著tcp負責保證你的資料可以完整而且有序的傳輸到另外一端。tcp是通過流的方式來傳輸資料的,這就意味這tcp會負責把你的資料切分,打包,然後具體傳輸。

最後記住,tcp傳輸其實就和讀寫檔案一樣簡單。

我們已經有一種可以像寫檔案一樣穩定傳輸資料的方法了,如果我們還想要一種可以自由的收發包的方法,我們可以怎麼做呢?

這裡我們可以用到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唯一能保證你的事情。其他事情都要靠你自己去訂製。

我們現在要做乙個選擇了。開發遊戲到底是用udp好呢?還是用tcp好呢?

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

tcp:

基於連線的協議。

可靠性和資料報的序列性是***的。

自動為你的資料封包。

確保包的流量不會超出你的網路鏈結的負載上限。

簡單易用,你只需要像寫檔案一樣去讀寫就萬事大吉了。

udp:

沒有連線的概念,如果你想要,自己去實現去。

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

你必須自己去封包。

你必須自己確保自己的資料報不會流量過大從而導致超過鏈結負載上限。

你必須自己處理包的丟失,重複,亂序的情況,如果你不想他們對你的程式造成麻煩,必須要自己實現**來做出應對。

tcp和udp都是基於ip協議的,但是他們的本質確實截然不同的。udp和它底層的ip協議類似,tcp卻將很多東西進行了抽象,它使你在使用它的時候感覺就像讀寫乙個檔案一樣,事實上他對你隱藏了很多複雜功能的實現細節。

它到底是如何實現這些細節的呢?

首先,tcp是流性質的協議,你將資料乙個位元乙個位元的寫入流,然後tcp來確保他們會最終到底目的地。我們必須明確:tcp協議是基於ip協議的,ip協議是基於資料報的。這裡tcp其實是把我們的資料流在底層進行了打包。事實上有一些tcp協議中的**就是把我們的資料流進行排隊,然後依次寫入包中,當包寫入了足夠多的資料以後,它就會把包發走。

這裡就會導致一些問題,因為你不能控制底層的打包和傳輸,所以當很小的使用者輸入資料寫入資料流的時候,tcp可能會湊滿一定量的資料(比如100bytes),然後再打包傳送。這樣的話,在實時性上面就會很差,因為也許你會需要這些包越快到達越好。這些小延遲也許就會大大的影響你的遊戲性。

tcp中其實有乙個tcp_nodelay的選項,使用這個選項以後,你的資料就會跳過tcp的佇列打包過程,直接傳送。

但是即使你使用的這個技術,你在多人網路遊戲中還是會遇到不小的問題。

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

tcp是如何實現可靠傳輸的

基本上來說,tcp將資料流中的資料做成封包,然後將他們通過不可靠的ip協議傳送,然後在接收端重組這些包成為資料流。

但是當乙個包丟失的時候tcp會做些什麼呢?當包重複和亂序的時候tcp又做了些什麼呢?

這裡我不想做太深入的介紹,有興趣的讀者可以在wiki上找到他們需要的細節。大致來說,tcp發現丟包的時候,會要求傳送者重發,重複的包會被丟棄,亂序包會被排序,事實上他就是這麼保證傳輸的可靠性的。

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

通過上面的論述,其實已經很明白了。在注重即時性的遊戲中,對於延遲的要求是很苛刻的,我們可以丟包,但是如果我們收到了比丟掉的包更新的包的話,我們完全可以不管丟掉的包。我們只關注當前資料。

這裡我們來假設乙個最簡單的多人遊戲的模型。比如乙個fps遊戲,你在客戶段每次將輸入的資料(比如前進,跳躍,**)傳送到伺服器端,然後伺服器端將玩家當前的位置和情況發回給客戶端來做顯示。

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

不幸的是你對tcp協議的這個行為完全無能為力。這是tcp協議的本性,就是它保證了tcp協議的可靠性的。

我們不需要這樣無法訂製的可靠性協議。我們需要自己進行訂製丟包時的處理原則。這也是我們在開發遊戲時,避免使用tcp協議的原因。

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

這個想法是很好的,我們可以在玩家操作等即時性很強的資料上使用udp協議,在玩家ai,資料載入,玩家對話等序列性很強的資料上使用tcp。如果你願意的話,甚至可以為不同的ai建立不同的tcp連線,以免乙個ai的丟包會影響的另外乙個ai的即時性。

我的建議是在遊戲中僅僅使用udp作為網路協議,即使要使用tcp也是自己在udp的基礎上實現一種類tcp的協議。這也是現代遊戲中流行的網路架構。

TiDB適用場景和不適用場景

一 tidb簡介 tidb 是 pingcap 公司受 google spanner f1 啟發而設計的開源分布式 htap hybrid transactional and analytical processing 資料庫,結合了傳統的 rdbms 和nosql 的最佳特性。tidb 相容 my...

HDFS適用場景和不適用場景

海量資料儲存 hdfs可橫向擴充套件,其儲存的檔案可以支援pb級別或更高階別的資料儲存。高容錯性 資料儲存多個副本,副本丟失後自動恢復。可構建在廉價的機器上,實現線性擴充套件。當集群增加新節點之後,namenode也可以感知,進行負載均衡,將資料分發和備份資料均衡到新的節點上。商用硬體 hadoop...

TiDB 的適用場景和不適用場景

典型的oltp場景 當您需要對海量資料 數十億行 進行隨機 實時讀 寫訪問時 實時 htap 場景 實時htap 混合事務 分析處理 要是有乙個使用tidb的類似oltp的場景,並且希望在tiflash的幫助下原地進行 olap分析時,新鮮的資料,對oltp效能無干擾 資料整合 有多個資料來源時,可...