1. 程式人生 > >8 傳輸層----TCP

8 傳輸層----TCP

情況 pen 四次揮手 選項 失效 處的 出現 font closed

8.1 TCP首部格式

技術分享圖片

  • 序號 :用於對字節流進行編號,指發送數據的位置,每發送一次數據,就累加一次該數據字節數的大小,序列號不會從0或1開始,而是在建立連接時由計算機生成的隨機數作為其初始值,例如序號為 301,表示第一個字節的編號為 301,如果攜帶的數據長度為 100 字節,那麽下一個報文段的序號應為 401。

  • 確認號 :期望收到的下一個報文段的序號。例如 B 正確收到 A 發送來的一個報文段,序號為 501,攜帶的數據長度為 200 字節,因此 B 期望下一個報文段的序號為 701,B 發送給 A 的確認報文段中確認號就為 701。

  • 數據偏移 :指的是數據部分距離報文段起始處的偏移量,實際上指的是首部的長度。

  • 保留:該字段主要是為了以後擴展時使用,其長度為4位。一般設置為0,但實際收到的包在該字段不為0,此包也不會被丟棄。
  • 確認 ACK :當 ACK=1 時確認號字段有效,否則無效。TCP 規定,在連接建立後所有傳送的報文段都必須把 ACK 置 1。

  • 同步 SYN :在連接建立時用來同步序號。當 SYN=1,ACK=0 時表示這是一個連接請求報文段。若對方同意建立連接,則響應報文中 SYN=1,ACK=1。

  • 終止 FIN :用來釋放一個連接,當 FIN=1 時,表示此報文段的發送方的數據已發送完畢,並要求釋放連接。

  • 窗口 :窗口值作為接收方讓發送方設置其發送窗口的依據。之所以要有這個限制,是因為接收方的數據緩存空間是有限的。

8.2 TCP三次握手

技術分享圖片

假設 A 為客戶端,B 為服務器端。

  • 首先 B 處於 LISTEN(監聽)狀態,等待客戶的連接請求。

  • A 向 B 發送連接請求報文,SYN=1,ACK=0,選擇一個初始的序號 x。

  • B 收到連接請求報文,如果同意建立連接,則向 A 發送連接確認報文,SYN=1,ACK=1,確認號為 x+1,同時也選擇一個初始的序號 y。

  • A 收到 B 的連接確認報文後,還要向 B 發出確認,確認號為 y+1,序號為 x+1。

  • B 收到 A 的確認後,連接建立。

三次握手的原因

第三次握手是為了防止失效的連接請求到達服務器,讓服務器錯誤打開連接。

客戶端發送的連接請求如果在網絡中滯留,那麽就會隔很長一段時間才能收到服務器端發回的連接確認。客戶端等待一個超時重傳時間之後,就會重新請求連接。但是這個滯留的連接請求最後還是會到達服務器,如果不進行三次握手,那麽服務器就會打開兩個連接。如果有第三次握手,客戶端會忽略服務器之後發送的對滯留連接請求的連接確認,不進行第三次握手,因此就不會再次打開連接。

8.3 TCP四次揮手

技術分享圖片

以下描述不討論序號和確認號,因為序號和確認號的規則比較簡單。並且不討論 ACK,因為 ACK 在連接建立之後都為 1。

  • A 發送連接釋放報文,FIN=1。

  • B 收到之後發出確認,此時 TCP 屬於半關閉狀態,B 能向 A 發送數據但是 A 不能向 B 發送數據。

  • 當 B 不再需要連接時,發送連接釋放報文,FIN=1。

  • A 收到後發出確認,進入 TIME-WAIT 狀態,等待 2 MSL(最大報文存活時間)後釋放連接。

  • B 收到 A 的確認後釋放連接。

四次揮手的原因

客戶端發送了 FIN 連接釋放報文之後,服務器收到了這個報文,就進入了 CLOSE-WAIT 狀態。這個狀態是為了讓服務器端發送還未傳送完畢的數據,傳送完畢之後,服務器會發送 FIN 連接釋放報文。

TIME_WAIT

客戶端接收到服務器端的 FIN 報文後進入此狀態,此時並不是直接進入 CLOSED 狀態,還需要等待一個時間計時器設置的時間 2MSL。這麽做有兩個理由:

  • 確保最後一個確認報文能夠到達。如果 B 沒收到 A 發送來的確認報文,那麽就會重新發送連接釋放請求報文,A 等待一段時間就是為了處理這種情況的發生。

  • 等待一段時間是為了讓本連接持續時間內所產生的所有報文都從網絡中消失,使得下一個新的連接不會出現舊的連接請求報文。

8.4 TCP可靠傳輸

TCP 使用超時重傳來實現可靠傳輸:如果一個已經發送的報文段在超時時間內沒有收到確認,那麽就重傳這個報文段。

一個報文段從發送再到接收到確認所經過的時間稱為往返時間 RTT,加權平均往返時間 RTTs 計算如下:

技術分享圖片

在上式中:(阿爾法 的值介於0到1,若很接近0,則表示舊的RTTs值和新的RTTs值相比變化不大,也就是說,新的RTT樣本不太影響RTTs; 若很接近1,則表明新的RTTs值,受當前采集的RTT樣本影響較大,跟上次的RTTs差距大)

RFC 2988:推薦的阿爾法值為1/8,也就是0.125 (這種方式得出的值更為平滑)。

超時時間 RTO 應該略大於 RTTs,TCP 使用的超時時間計算如下:

技術分享圖片 其中 RTTd 為偏差。 8.5 TCP以段為單位發送數據 在建立TCP連接的同時,也可以確定發送數據包的單位,我們也可以稱其為“最大消息長度”(MSS:Maximum Segment Size)。最理想情況是,最大消息長度正好是IP中不會被分片處理的最大數據長度。 TCP在傳送大量數據時,是以MSS的大小將數據進行分割發送。進行重發也是以MSS為單位。 MSS 是在三次握手的時候,在兩端主機之間被就計算得出。兩端的主機在發出建立連接的請求時,會在TCP首部中寫入MSS選項,告訴對方自己的接口能夠適應的MSS的大小。然後會在兩者之間選擇一個較小的值投入使用。 技術分享圖片

8.6 利用窗口控制提高速度

TCP以1個段為單位,每發一個段進行一次確認應答處理,這樣的傳輸方式的一個缺點是,包的往返時間越長通信性能就越低。

技術分享圖片

為解決這個問題,TCP引入了窗口的概念。即使在往返時間較長的情況下,也能控制網絡性能的下降。如下圖所示,確認應答不再是以每個分段,而是以更大的單位進行確認,轉發時間會被大幅度的縮短。也就是說,發送端主機,在發送了一個段以後不必一直等待確認應答,而是繼續發送。 技術分享圖片

窗口的大小就是指無需等待確認應答而可以繼續發送數據的最大值,上圖中,窗口的大小是4個段。

在下圖中,發送數據中高亮圈起的部分正是前面所提到的窗口。在這個窗口內的數據即使沒有收到確認應答也可以被發送出去。不過在整個窗口的確認應答沒有到達之前,如果部分數據包出現丟包,那麽發送端仍要負責重傳。為此,發送端主機得設置緩存保留這些待被重傳的數據,知道收到它們的確認應答。

在滑動窗以外的部分包括尚未發送的數據以及已經確認對端已收到的數據。當數據發出後若如期收到確認應答就可以不用再進行重發,此時數據就可以從緩存區清除。

在收到確認應答的情況下,將窗口滑動到確認應答中的序列號的位置。這樣可以順序的將多個段同時發送提高通信性能。這種機制也被稱為滑動窗口控制。

技術分享圖片

8.7 窗口控制與重發控制

在使用窗口控制中,如果出現段丟失怎麽辦?

第一種情況:確認應答未能返回

在沒有使用窗口控制的時候,沒有收到確認應答的數據都會重發。而使用了窗口控制,某些確認應答即使丟失也無需重發。

技術分享圖片

第二種情況:某一個報文段丟失

接收主機如果收到一個自己應該接收的序號以外的數據時,會針對當前為止收到的數據返回確認應答。

例如下圖的例子:當某一報文丟失後,發送端回一直收到序號為1001的確認應答,這個確認應答好像是在提醒發送端“我想接收的是從1001開始的數據”。因此,在窗口比較大,又出現報文段丟失的情況下,同一個序號的確認應答將會被重復不斷的返回。而發送端主機如果連續3次收到同一個確認應答,就會將其所對應的數據進行重發。

技術分享圖片

8.8 TCP流量控制

流量控制是為了控制發送方發送速率,保證接收方來得及接收。

接收方發送的確認報文中的窗口字段可以用來控制發送方窗口大小,從而影響發送方的發送速率。將窗口字段設置為 0,則發送方不能發送數據。

技術分享圖片

如上圖所示,當接收端收到從3001號開始的數據段後其緩沖期即滿,不得不暫時停止接收數據。之後,在後代發送窗口更新通知之後通信才得以繼續進行。如果這個窗口的更新通知在傳輸途中丟失,可能會導致無法繼續通信。為避免此類問題,發送端主機會時不時的發送一個叫做窗口探測的數據段。

8.9 TCP擁塞控制

有TCP窗口控制,收發主機之間即使不再以一個數據段為單位發送確認應答,也能夠發送大量數據包。然而,如果在通信剛開始就發送大量數據,也可能會引發擁塞,如果網絡出現擁塞,分組將會丟失,此時發送方會繼續重傳,從而導致網絡擁塞程度更高。因此當出現擁塞時,應當控制發送方的速率。這一點和流量控制很像,但是出發點不同。流量控制是為了讓接收方能來得及接收,而擁塞控制是為了降低整個網絡的擁塞程度。

TCP 主要通過四個算法來進行擁塞控制:慢開始、擁塞避免、快重傳、快恢復。

發送方需要維護一個叫做擁塞窗口(cwnd)的狀態變量,註意擁塞窗口與發送方窗口的區別:擁塞窗口只是一個狀態變量,實際決定發送方能發送多少數據的是發送方窗口。

為了便於討論,做如下假設:

  • 接收方有足夠大的接收緩存,因此不會發生流量控制;
  • 雖然 TCP 的窗口基於字節,但是這裏設窗口的大小單位為報文段。

技術分享圖片

1. 慢開始與擁塞避免

發送的最初執行慢開始,令 cwnd = 1,發送方只能發送 1 個報文段;當收到確認後,將 cwnd 加倍,因此之後發送方能夠發送的報文段數量為:2、4、8 ...

註意到慢開始每個輪次都將 cwnd 加倍,這樣會讓 cwnd 增長速度非常快,從而使得發送方發送的速度增長速度過快,網絡擁塞的可能性也就更高。設置一個慢開始門限 ssthresh,當 cwnd >= ssthresh 時,進入擁塞避免,每個輪次只將 cwnd 加 1。

如果出現了超時,則令 ssthresh = cwnd / 2,然後重新執行慢開始。

2. 快重傳與快恢復

在接收方,要求每次接收到報文段都應該對最後一個已收到的有序報文段進行確認。例如已經接收到 M1 和 M2,此時收到 M4,應當發送對 M2 的確認。

在發送方,如果收到三個重復確認,那麽可以知道下一個報文段丟失,此時執行快重傳,立即重傳下一個報文段。例如收到三個 M2,則 M3 丟失,立即重傳 M3。

在這種情況下,只是丟失個別報文段,而不是網絡擁塞。因此執行快恢復,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,註意到此時直接進入擁塞避免。

慢開始和快恢復的快慢指的是 cwnd 的設定值,而不是 cwnd 的增長速率。慢開始 cwnd 設定為 1,而快恢復 cwnd 設定為 ssthresh。

技術分享圖片

8 傳輸層----TCP