【TCP通信】原理詳解與編程實現(一)


本文主要是對韓立剛計算機網絡視頻課程TCP通信部分的總結和整理,並參考了其它相關博客。
本文主要是理論知識。
下一篇文章將進行編碼實現【TCP通信】原理詳解與編程實現(二)

1.TCP簡介

TCP協議,傳輸控制協議(英語:Transmission Control Protocol,縮寫爲:TCP)是一種面向連接的、可靠的、基於字節流的通信協議

TCP把連接作爲最基本的抽象單元,每條TCP連接有兩個端點,TCP連接的端點即套接字
套接字socket = (IP地址+端口號)
TCP連接={socket1,socket2}={(IP1:port1),(IP2,port2)}
TCP提供全雙工通信。

2.TCP報文

首部中的重要概念
序號:Seq序號,佔32位。用於說明當前數據第一個字節在所有數據(整個文件)中的位置
確認號:Ack序號,佔32位。用於告訴發送者接下來需要發送的數據序號。
數據偏移:用於說明首部長度。(比如1111說明首部長爲15*4字節)
標誌位:tcp標誌位有6種:

SYN(synchronous發起一個新連接) 
ACK(acknowledgement 確認)
PSH(push傳送) 
FIN(finish結束)
RST(reset重置) 
URG(urgent緊急)

不要將確認序號Ack與標誌位中的ACK搞混
窗口:表示發送/接收緩存窗口大小。如下圖。
在這裏插入圖片描述

3.TCP建立與斷開連接

3.1 TCP的三次握手

三次握手其實就是建立連接的過程。其過程如圖:

1)第一次握手:Client將標誌位SYN(建立新連接)置爲1,隨機產生一個值seq=x,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。
2)第二次握手:Server收到數據包後由標誌位SYN=1知道Client請求建立連接,Server將標誌位SYN和ACK(確認)都置爲1ack=x+1,隨機產生一個值seq=y,並將該數據包發送給Client以確認連接請求,Server進入SYN_RCVD狀態。
3)第三次握手:Client收到確認後,檢查ack是否爲x+1,ACK是否爲1,如果正確則將標誌位ACK置爲1,ack=y+1,並將該數據包發送給Server,Server檢查ack是否爲y+1,ACK是否爲1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間可以開始傳輸數據了。

三次握手的通俗理解

3.2 TCP的四次揮手

四次揮手其實就是斷開連接的過程。過程如圖:

1)第一次揮手:客戶端向服務器發起請求釋放連接的TCP報文,置FIN爲1。客戶端進入終止等待-1階段
2)第二次揮手:服務器端接收到從客戶端發出的TCP報文之後,確認了客戶端想要釋放連接,服務器端進入CLOSE-WAIT階段,並向客戶端發送一段TCP報文。客戶端收到後進入種植等待-2階段

3)第三次揮手:服務器做好了釋放服務器端到客戶端方向上的連接準備,再次向客戶端發出一段TCP報文。。此時服務器進入最後確認階段
4)第四次揮手:客戶端收到從服務器端發出的TCP報文,確認了服務器端已做好釋放連接的準備,於是進入時間等待階段,並向服務器端發送一段報文。注意:第四次揮手後客戶端不會立即進入closed階段,而是等待2MSL再關閉。

四次揮手的通俗理解

4.TCP數據傳輸示意

以下圖爲例(計算機訪問一個網站)說明傳輸過程:

1)計算機訪問網站,源端口爲1057,目標端口爲80,序號爲1,確認號爲1,數據長203字節。
2)網站返回數據,確認號爲204,發送1-1460數據。
3)網站接着發1461-2053數據,確認號依然爲204.(表明計算機發的203個字節已經接收到)
4)計算機確認收到2053字節的數據,但自身發送的數據爲空。

5.TCP如何實現可靠傳輸

5.1 停止等待方式

需要停止等待確認,若設定時間內未收到確認則進行超時重傳。這樣可以保證對方確認收到後,再發送下一段報文。

確認丟失與確認遲到

上述的確認和重傳機制,可以稱爲自動重傳機制ARQ(Automatic repeat reQuest)
但是簡單的停止等待方式信道利用率較低,爲此採用流水線傳輸方式

5.2 流水線傳輸方式

流水線傳輸
發送方可連續發送多個分組,不必每發完一個分組就停頓下來等待對方的確認。由於信道上一直有數據不間斷的傳送,這種傳輸方式可獲得很高的信道利用率。

連續ARQ協議 / 滑動窗口
上述發送端是維持滑動窗口實現流水線傳輸的,如下圖:

累計確認
接收方一般採用累計確認的方式表明自己已經連續接收到哪個地方了

5.3 可靠傳輸實例:

前面已經簡單說明了tcp可靠傳輸的大致原理。這裏具體舉例說明。
假設,A計算機要發送一個文件(1-40字節)到B計算機
1)首先計算機A將緩存中的數據依次發送出去(多個數據包),在B確認之前將不會刪除這些數據

2)計算機B確認收到前兩個數據包,併發送一個數據包(確認號爲7)給A,於是A知道前6個字節已經發送成功,緩存窗口可以移動,捨棄前6個字節.

3)A繼續發送窗口中的數據,B的接收窗口右移,B又接收到新數據,再向A確認新數據收到,A繼續發送新數據。

4)丟包的情況
假設A發的三個數據包中,只有第二個丟了,而一、三數據包沒有丟,那麼B只會確認第一個數據包,於是A超時重傳第二個數據包,B重新接收到第二個數據包後,會直接確認第三個數據包,這樣A就不用重傳第三個數據包了。

6.TCP流量控制

TCP流量控制
概念
接收端處理數據的速度是有限的,如果發送方的速度太快,就會把緩衝區u打滿。這個時候如果繼續發送數據,就會導致丟包等一系列連鎖反應。所以TCP支持根據接收端能力來決定發送端的發送速度。這個機制叫做流量控制。

窗口大小
(接收端向發送端主機通知自己可以接受數據的大小,這個大小限制就叫做窗口大小)

機理
接收端將自己可以接收的緩衝區大小放入 TCP 首部中的 “窗口大小” 字段, 通過ACK端通知發送端;窗口大小字段越大, 說明網絡的吞吐量越高;
接收端一旦發現自己的緩衝區快滿了, 就會將窗口大小設置成一個更小的值,通知給發送端;發送端接受到這個窗口之後, 就會減慢自己的發送速度;
如果接收端緩衝區滿了, 就會將窗口置爲0; 這時發送方不再發送數據, 但是需要定期發送一個窗口探測數據段, 使接收端把最新的窗口大小告訴發送端,以便繼續發送數據。

其過程示意如圖
在這裏插入圖片描述

7.TCP擁塞控制

在不清楚當前網絡狀態下, 貿然發送大量的數據, 可能引起計算機網絡的擁堵.
TCP引入慢啓動機制, 先發少量的數據, 探探路, 摸清當前的網絡擁堵狀態, 再決定按照多大的速度傳輸。如下圖:
在這裏插入圖片描述
每次發送數據包的時候, 將擁塞窗口和接收端主機反饋的窗口大小做比較, 取較小的值作爲實際發送的窗口;像上面這樣的擁塞窗口增長速度, 是指數級別的. “慢啓動” 只是指初使時慢, 但是增長速度非常快. 爲了不增長的那麼快, 因此不能使擁塞窗口單純的加倍.此處引入一個叫做慢啓動的閾值

當擁塞窗口超過這個閾值的時候, 不再按照指數方式增長, 而是按照線性方式增長

乘法減少:出現一次超時(即出現一次網絡擁塞),就把慢開始門限值ssthresh設置爲當前的擁塞窗口值乘以0.5
在這裏插入圖片描述

8.TCP相關面試題

【問題1】爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?

答:因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,“你發的FIN報文我收到了”。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。

【問題2】爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最後一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最後的ACK回覆,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重複發送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK之後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。

【問題3】爲什麼不能用兩次握手進行連接?

答:3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被髮送和確認。

現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作爲例子,考慮計算機S和C之間的通信,假定C給S發送一個連接請求分組,S收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,S認爲連接已經成功地建立了,可以開始發送數據分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什麼樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認爲連接還未建立成功,將忽略S發來的任何數據分 組,只等待連接確認應答分組。而S在發出的分組超時後,重複發送同樣的分組。這樣就形成了死鎖。

【問題4】如果已經建立了連接,但是客戶端突然出現故障了怎麼辦?

TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。

參考

《計算機網絡》視頻課程韓立剛

詳解 TCP 連接的“ 三次握手 ”與“ 四次揮手 ”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章