協議森林08 不放棄 (TCP協議與流通信)

TCP(Transportation Control Protocol)協議與IP協議是一同產生的。事實上,兩者最初是一個協議,後來才被分拆成網絡層的IP和傳輸層的TCP。我們已經在UDP協議中介紹過,UDP協議是IP協議在傳輸層的“傀儡”,用來實現數據包形式的通信。而TCP協議則實現了“流”形式的通信。
2. 如何實現可靠傳輸
TCP協議是傳輸層協議,實現的是端口到端口(port)的通信。更進一步,TCP協議虛擬了文本流(byte stream)的通信。在Linux文本流中我們談到,計算機數據的本質是有序的0/1序列 (如果以byte爲單位,就叫做文本流)。計算機的功能就是儲存和處理文本流。CPU + memory + 存儲設備實現了文本流在同一臺計算機內部的加工處理。通過一些IO,比如屏幕和鍵盤,文本流實現了人機交互。而進一步,如果網絡通信可在不同計算機之間進行文本流的交互,那麼我們就和整個計算機系統的數據處理方式實現了對接。
(給文本流分段是在發送主機完成的,而碎片化是在網絡中的路由器完成的。路由器要處理許多路的通信,所以相當繁忙。文本流提前在發送主機分好段,可以避免在路由器上執行碎片化,可大大減小網絡負擔)
TCP片段的頭部(header)會存有該片段的序號(sequence number)。這樣,接收的計算機就可以知道接收到的片段在原文本流中的順序了,也可以知道自己下一步需要接收哪個片段以形成流。比如已經接收到了片段1,片段2,片段3,那麼接收主機就開始期待片段4。如果接收到不符合順序的數據包(比如片段8),接收方的TCP模塊可以拒絕接收,從而保證呈現給接收主機的信息是符合次序的“流”。

片段編號這個初步的想法並不能解決我們所有的問題。IP協議是不可靠的,所以IP數據包可能在傳輸過程中發生錯誤或者丟失。而IP傳輸是"Best Effort" 式的,如果發生異常情況,我們的IP數據包就會被輕易的丟棄掉。另一方面,如果亂序(out-of-order)片段到達,根據我們上面說的,接收主機不會接收。這樣,錯誤片段、丟失片段和被拒片段的聯手破壞之下,接收主機只可能收到一個充滿“漏洞”的文本流。

TCP的補救方法是,在每收到一個正確的、符合次序的片段之後,就向發送方(也就是連接的另一段)發送一個特殊的TCP片段,用來知會(ACK,acknowledge)發送方:我已經收到那個片段了。這個特殊的TCP片段叫做ACK回覆。如果一個片段序號爲L,對應ACK回覆有回覆號L+1,也就是接收方期待接收的下一個發送片段的序號。如果發送方在一定時間等待之後,還是沒有收到ACK回覆,那麼它推斷之前發送的片段一定發生了異常。發送方會重複發送(retransmit)那個出現異常的片段,等待ACK回覆,如果還沒有收到,那麼再重複發送原片段... 直到收到該片段對應的ACK回覆(回覆號爲L+1的ACK)。
當發送方收到ACK回覆時,它看到裏面的回覆號爲L+1,也就是發送方下一個應該發送的TCP片段序號。發送方推斷出之前的片段已經被正確的接收,隨後發出L+1號片段。ACK回覆也有可能丟失。對於發送方來說,這和接收方拒絕發送ACK回覆是一樣的。發送方會重複發送,而接收方接收到已知會過的片段,推斷出ACK回覆丟失,會重新發送ACK回覆
面對“挫折”,TCP協議的態度: never give up
同樣面對“挫折”,UDP的態度: who cares...

上面的工作方式中,發送方保持發送->等待ACK->發送->等待ACK...的單線工作方式,這樣的工作方式叫做stop-and-wait。stop-and-wait雖然實現了TCP通信的可靠性,但同時犧牲了網絡通信的效率。在等待ACK的時間段內,我們的網絡都處於閒置(idle)狀態。我們希望有一種方式,可以同時發送出多個片段。然而如果同時發出多個片段,那麼由於IP包傳送是無次序的,有可能會生成亂序片段(out-of-order),也就是後發出的片段先到達。在stop-and-wait的工作方式下,亂序片段完全被拒絕,這也很不效率。畢竟,亂序片段只是提前到達的片段。我們可以在緩存中先存放它,等到它之前的片段補充完畢,再將它綴在後面。然而,如果一個亂序片段實在是太過提前(太“亂”了),該片段將長時間佔用緩存。我們需要一種折中的方法來解決該問題:利用緩存保留一些“不那麼亂”的片段,期望能在段時間內補充上之前的片段(暫不處理,但發送相應的ACK);對於“亂”的比較厲害的片段,則將它們拒絕(不處理,也不發送對應的ACK)。

 
總結
<span courier="" new',="" courier;="" "="" style="padding: 0px; margin: 0px; color: rgb(80, 80, 80);">TCP協議和UDP協議走了兩個極端。TCP協議複雜但可靠,UDP協議輕便但不可靠。在處理異常的時候,TCP極端負責,而UDP一副無所謂的樣子。在TCP中,分段和編號實現了次序;ACK和重新發送實現了可靠性;sliding window則讓上面的機制更加有效率的運行。Never give up,這就是TCP協議的態度。
這篇文章也包含了我的一個視頻小實驗,看看效果如何,歡迎大家的反饋。
作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!
發佈了14 篇原創文章 · 獲贊 11 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章