上一篇 TCP 在做什麼?簡單介紹了 TCP 大致的框架,以及是如何建立連線的,今天來看看為何 TCP 是一個可靠的協定?
首先我們先來看看資料「損壞」這件事情。現實世界中的如果送包裹,過程中沒有壓到、摔到,完好無缺的抵達目的地,我們就說這個包裹沒有損壞。但在網路世界不太一樣,資料被轉換成電流或是無線電波傳送,如果突然打了個雷之類的讓介質中有什麼干擾,傳播中的資料肯定就此毀壞。
還好,我們傳送的資訊都數位化了,如果這次傳送的資訊壞了會沒收到,大不了再傳一次,成本反正很低,這可是真實世界的包裹難以達成的。也就是說,如果資料「損壞」了,在網路世界只要重新傳送就好,重點就在怎麼檢查資料在傳輸過程中還完不完好。
由於資料會被拆成數個封包傳送,TCP 找出錯誤的方式便有以下幾種方式:檢驗資訊是否有誤、封包掉了就重送、看看序號是否連續。
序號連續這件事在聊 TCP 三向交握的時候提了一些,所以我們接著來看看檢驗資料錯誤和重送機制吧。
要檢驗資訊是否有誤,TCP 的解法是 Checksum,就是檢驗某些數值的加總是否一致,這在計算機領域也是常用來做錯誤偵測的一種方法。
由於傳輸的資料是數位的,最基本的模樣由 0 和 1 所組成,我們 TCP 就把 Port、序號、要傳的資料等等這些數字化的資訊加總在一起,所以稱做檢驗「和」(Sum)。這個「和」也會被放在這筆資料內一起送出去,接收的時候把傳送的資料和這個「和」驗證一下。
舉個例子來說,我們傳的資料是 1 3 5 7 9 1
,Checksum 就是把這些數字加起來,得到 26
。但是當然不會把加起來的數字直接傳過去,因為要傳的資料可能很長,得到的 Checksum 就會很大,TCP 的定義不容許太大的 Checksum 存在,因此我們可以對這個 Checksum 做點調整,例如取個除以 10 的餘數,26 % 10 = 6
。
------- 1 3 5 7 9 1 ------->
1 + 3 + 5 + 7 + 9 + 1 = 26
26 % 10 = 6
把取完的餘數 6
一起傳過去,接收的時候重新加一下驗證是否等於 6
,如果不是的話,就重新傳送一次。以上例子並非 TCP Checksum 真實的情境,只是把概念用一般人比較容易理解的 10 進制來表示而已。
大致了解 Checksum 之後,你可能會想問,有沒有可能傳的資料錯了,但得出的 Checksum 還是一樣的?
很有可能。
機率大約是 0.0016%。你可能覺得機率蠻低了,但放大到每天不知道多少筆的 TCP 封包在網路上跑著,根據大數法則,發生錯誤沒被揪出來的封包比比皆是。
所以說,Checksum 雖然能揪出大部分的錯誤,但其實算是蠻脆弱的錯誤檢驗機制,現在是依靠著網路模型中其它層也會做的一些錯誤檢測機制,一起和 TCP 避免資料的錯誤產生。
TCP 雖然號稱可靠的傳輸協定,但重點還是擺在讓要傳的封包一定會傳到目的地,或是傳不到也一定讓你知道。
那麼,TCP 要怎麼確保送的封包已經到達目的地了呢?其實方法說起來也很簡單,靠的就是它的內建計時器。
如果我方已經將封包送出一陣子了,還沒得到對方回應說收到,很有可能這個封包在路上就掛了。所以 TCP 會在送出封包後計時,1 秒鐘 2 秒鐘 …,時間到。還沒收到回覆,再送一次。
具體計的時間其實不是固定的數值,剛開始可能從 10 毫秒等起,如果沒得到回覆,下次就等 20 毫秒、40 毫秒,以此類推,這種做法也是因為怕說到目的地的路徑太壅塞了,如果我相同時間一直瘋狂重送封包,可能讓路徑更塞。
有了壅塞的狀況,也可能會有一路暢通,傳的太快讓收的那方措手不及的情形發生,這時 TCP 也會跳出來做流量的控制。
具體怎麼做的呢?就是將來得太快的資料放在如同行李轉盤的記憶體上,慢慢消化,如果轉盤已經放滿資料了,接收方就會叫傳送方先別傳了,等一等再來。
以上為 TCP 對於資料傳輸的簡介,而在傳輸層還有另一大協定 UDP 呢,我們接著來看看。