運輸層——TCP協議

1. 報文格式

在這裏插入圖片描述
序號:佔4字節。序號範圍是 0 到 2 的32次方-1 ,序號增加到 2的32次方-1 後,下一個序列號就回到了1。也就是說,序號使用mod 2的32次方 運算。TCP是面向字節流的,TCP連接中傳送的字節流中的每一個字節都按順序編號。首部中的序號就是指本報文段所發送數據的第一個字節的序號

確認號:佔4個字節,是期望收到對方下一個報文段的一個數據字節的序號

確認ACK:當ACK=1時,確認號有效,當ACK=0時,確認號無效。當建立連接後所有傳送的報文段都必須把 ACK 置1。

同步SYN:當SYN=1,ACK=0 時,表明這是一個連接請求報文段。對方若同意建立連接,則應在響應的報文段中使 SYN=1 和 ACK= 1 。因此, SYN 置爲 1 就表示這是一個連接請求或連接接受報文。

終止FIN:當FIN=1時。表明此報文的發送方的數據已經發送完畢,並要求釋放運輸連接。

2. 三次握手

在這裏插入圖片描述

  1. 客戶端發起連接請求報文段,SYN = 1,自己的初始序號 seq = x
  2. 當服務器接收到請求後,發送一個連接接受報文段,SYN=1,ACK=1,自己的初始序號 seq = y,確認號 ack = x + 1
  3. 當客戶端收到接受報文後,再發送一條確認,此時ACK=1,確認號 ack = y + 1,序號 x + 1

丟包情況:

第一個包,即 A 發給 B 的 SYN 中途丟失,沒有到達 B :

A 會週期性超時重傳,直到收到 B 的確認。

第二個包,即 B 發送給 A 的 SYN + ACK 中途丟失,沒有到達 A :

B 會週期性超時重傳,直到收到 A 的確認。

第三個包,即 A 發送給 B 的 ACK 中途丟失,沒有到達 B :

A 發完 ACK ,單方面認爲 TCP 爲 Established 狀態,而 B 顯然認爲 TCP 爲 Active 狀態:

a.假定此時雙方都沒有數據發送,B 會週期性超時重傳,直到收到 A 的確認,收到之後連接建立。

b.假定此時 A 有數據發送,B 收到 A 的 Data + ACK ,自然會切換爲 Established 狀態。

c.假定此時 B 有數據發送,發送不了,B 會週期性超時重傳,直到收到 A 的確認,收到之後連接建立。

爲什麼需要三次握手,二次和四次不行?

TCP作爲一種可靠傳輸控制協議,既要保證數據可靠傳輸,又要提高傳輸的效率,而三次恰恰可以滿足這兩方面的需求。

四次握手過程:

  1. A 發送同步信號 SYN + A 的初始序號x
  2. B 發送一個確認報文段 (ACK= 1, ack = x + 1)
  3. B 再發送一個同步報文段 (SYN = 1, seq = y)
  4. A 發送一個確認報文段(ACK= 1, ack = y + 1)

顯然 2、3 步驟可以合併,提高連接速度與效率。

兩次握手過程:

  1. A 發送同步信號 SYN + A 的初始序號x
  2. B 發送同步信號 SYN + B 的初始序號y + 確認 ACK = 1 + 確認序號 x + 1

這裏的問題是,此時 A 與 B 就 A 的初始序號達成了一致,但是 B 無法知道 A 是否已經接收到自己的同步信號,如果這個同步信號丟失了,A 和 B 就B的初始序號將無法達成一致。

一句話概括,TCP 連接握手,握的是啥?

通信雙方數據原點的序列號。

3. 四次揮手

在這裏插入圖片描述

  1. A 的應用進程先向其 TCP 發出連接釋放報文段,並停止再發送數據,主動關閉 TCP 連接。 A 把連接釋放報文段首部的終止控制位 FIN 置 1, 其序號 seq = u, 它等於前面已傳送過的數據的最後一個字節的序號加 1 。這時 A 進入 FIN-WAIT-1 (終止等待 1) 狀態,等待 B 的確認。
  2. B 收到連接釋放報文段後即發出確認,確認號是 ack = u + 1, 而這個報文段自己的序號是 V, 等於 B 前面已傳送過的數據的最後一個字節的序號加 1 。然後 B 就進入 CLOSEWAIT (關閉等待)狀態。TCP 服務器進程這時應通知高層應用進程,因而從 A 到 B 這個方向的連接就釋放了,這時的 TCP 連接處於半關閉 (half-close)狀態,即 A 已經沒有數據要發送了,但 B 若發送數據, A 仍要接收。也就是說,從 B 到 A 這個方向的連接並未關閉,這個狀態可能會持續一段時間。 A 收到來自 B 的確認後,就進入 FIN-WAIT-2 (終止等待 2) 狀態,等待 B 發出的連接釋放報文段。
  3. 若 B 已經沒有要向 A 發送的數據,其應用進程就通知 TCP 釋放連接。這時 B 發出的連接釋放報文段必須使 FIN= 1 。現假定 B 的序號爲 w (在半關閉狀態 B 可能又發送了一些數據)。 B 還必須重複上次已發送過的確認號 ack = u + 1 。這時 B 就進入 LAST-ACK (最後確
    認)狀態,等待 A 的確認。
  4. A 在收到 B 的連接釋放報文段後,必須對此發出確認。在確認報文段中把 ACK 置 1,確認號 ack = w + 1, 而自己的序號是 seq=u+1。但此時TCP連接並沒有釋放掉,A還需要經過時間等待計時器設置的時間2MSL後,TCP連接才完全釋放。第一爲了保證 A 發送的最後一個 ACK 報文段能夠到達 B 。第二,A 在發送完最後一個 ACK 報文段後,再經過時間 2MSL, 就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣就可以使下一個新的連接中不會出現這種舊的連接請求報文段。

爲什麼是4次揮手?

最本質的原因在於TCP是全雙工,數據是雙向流動的,沒有所謂的主從關係。客戶機請求斷開,只是客戶機不會再向服務器發送數據了。這個時候服務器還可以繼續處理客戶機之前發送上來的數據,然後返回給客戶機,四次斷開就給服務器留下了一個處理尾部數據的時間,當服務器數據全部處理完了,並且也返回給客戶機了,這個時候服務器就同樣可以發送 FIN 信號了。這個完全符合我們生活之中實際的例子。

4. TCP 怎麼保證可靠性

4.1 TCP 是面向連接的字節流協議

連接意味着需要三次握手和四次揮手,確保連接和斷開的過程可靠。

4.2 超時重傳、應答及數據校驗機制

TCP 每發出報文,都會在發送時設置一個重傳定時器,如果當定時器溢出時還沒有收到確認,它就重傳該數據;並且當收到的數據報校驗出錯,主端不會發送響應報文,直到對端重傳。

4.3 慢啓動和擁塞控制

爲什麼需要慢啓動?

當主機開始發送數據時,由於並不清楚網絡的負荷情況,所以如果立即把大量數據字節注入到網絡,那麼就有可能引起網絡發生擁塞。經驗證明,較好的方法是先探測一下,即由小到大逐漸增大發送窗口,也就是說,由小到大逐漸增大擁塞窗口數值。

爲什麼需要擁塞避免?

慢啓動完成之後,擁塞窗口會持續增大,但是當擁塞窗口增加過快,可能導致過多的數據注入到網絡中,引起整個網絡的擁塞,從而需要擁塞避免。

什麼時候確定擁塞發生?

發送方發送一些報文段時,如果發送方沒有在時間間隔內收到接收方的確認報文段(響應超時),則就可以認爲網絡出現了擁塞,就可以進入擁塞避免算法。

慢啓動和擁塞避免算法原理?

擁塞避免算法和慢啓動算法需要對每個連接維持兩個變量:一個擁塞窗口cwnd(用來表示發送方在得到接收方確認前,最大允許傳輸的未經確認的數據)和一個慢啓動門限ssthresh(超過此門限則啓動擁塞避免算法),通過兩個變量的值確定使用慢啓動算法還是擁塞避免算法。

慢啓動算法:就是在主機剛開始發送數據報的時候先探測一下網絡的狀況,如果網絡狀況良好,發送方每發送一次文段都能正確的接受確認報文段。那麼就從小到大的增加擁塞窗口的大小,即增加發送窗口的大小。慢啓動算法是指數增加,初始設置cwnd爲1個報文段,此後每收到一個確認就加1,那樣,這會使窗口按指數方式增長:發送1個報文段,然後是2個,接着是4個等等。 慢啓動簡單的例子:開始發送方先設置cwnd(擁塞窗口)=1,發送第一個報文段M1,接收方接收到M1後,發送方接收到接收方的確認後,把cwnd增加到2,接着發送方發送M2、M3,發送方接收到接收方發送的確認後cwnd增加到4,慢啓動算法每經過一個傳輸輪次(認爲發送方都成功接收接收方的確認),擁塞窗口cwnd就加倍。

擁塞避免算法:爲了防止cwnd增加過快而導致網絡擁塞,所以在適當的時候需要啓動擁塞避免算法。擁塞避免算法使得cwnd緩慢的增加而不是加倍的增長,每經歷過一次往返時間就使cwnd增加1,而不是加倍。這樣使cwnd緩慢的增長,比慢啓動要慢的多。

當擁塞發生時候,兩種算法如何配合工作? 無論是慢啓動算法還是擁塞避免算法,只要判斷網絡出現擁塞,就要把慢啓動開始門限(ssthresh)設置爲發送窗口的一半(>=2),cwnd(擁塞窗口)設置爲1,然後再使用慢啓動算法,這樣做的目的能迅速的減少主機向網絡中傳輸數據,使發生擁塞的路由器能夠把隊列中堆積的分組處理完畢。慢啓動算法擁塞窗口按指數增加,擁塞窗口是按照線性的規律增長,比慢啓動算法擁塞窗口增長慢的多。

二者配合工作簡單實例:

  1. TCP 連接進行初始化的時候,cwnd=1,ssthresh=16。
  2. 連接剛開始使用慢啓動算法發送數據,在慢啓動算法開始時,cwnd的初始值是1,每次發送方收到一個ACK擁塞窗口就增加1,當ssthresh = cwnd時,就啓動擁塞控制算法,擁塞窗口按照規律增長。
  3. 當cwnd=24時,網絡出現超時,發送方收不到確認ACK,此時設置ssthresh=12,(二分之一cwnd),並設置cwnd=1,然後重新開始慢啓動算法,當cwnd = ssthresh = 12,慢啓動算法變爲擁塞控制算法,cwnd按照線性的速度進行增長。

在這裏插入圖片描述

4.4 快重傳與快恢復

快速重傳:針對接收方收到失序報文的算法。快重傳算法要求首先接收方收到一個失序的報文段後就立刻發出重複確認,而不要等待自己發送數據時才進行捎帶確認。例如當接收方成功的接受了發送方發送來的M1、M2並且分別給發送了ACK,現在接收方沒有收到M3,而接收到了M4,顯然接收方不能確認M4,因爲M4是失序的報文段。如果根據可靠性傳輸原理接收方什麼都不做(如果接收方需要發送數據也可以將M2的ACK重新捎帶發過去),但是按照快速重傳算法,在收到M4、M5等報文段的時候,不斷重複的向發送方發送M2的ACK。該重複的ACK的目的在於讓對方知道收到一個失序的報文段,並告訴對方自己希望收到的序號告訴對方我要M3啊,你快點發給我。ACK序列其實就是我這邊要接收的下一個報文。如果接收方一連收到三個重複的ACK,那麼發送方不必等待重傳計時器到期,直接重傳相應的報文。如果1,2,4,5號的收到了,3號丟失,那麼發送端僅重發3還是全部重發3,4,5。快速重傳,連續發送三次2號的ACK告訴你發送3號過來。然後再響應5號,這樣發送方就知道。

快速恢復算法:當發送發連續接收到三個確認時,就執行擁塞避免算法,把慢啓動開始門限(ssthresh)減半,但是接下來並不執行慢啓動算法。而是把cwnd設置爲ssthresh的一半, 然後執行擁塞避免算法,使擁塞窗口緩慢增大,這就是快速恢復算法。

在這裏插入圖片描述

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