天天看點

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

關于TCP的四層結構

參考上一篇部落格: https://blog.csdn.net/q5706503/article/details/85641790

TCP三向交握

所謂三次握手(Three-way Handshake),是指建立一個TCP連接配接時,需要用戶端和伺服器總共發送3個包。

三次握手的目的是連接配接伺服器指定端口,建立TCP連接配接,并同步連接配接雙方的序列号和确認号并交換 TCP 視窗大小資訊.在socket程式設計中,用戶端執行connect()時。将觸發三次握手。

兩個序号和三個标志位:

  (1)序号:seq序号,占32位,用來辨別從TCP源端向目的端發送的位元組流,發起方發送資料時對此進行标記。

  (2)确認序号:ack序号,占32位,隻有ACK标志位為1時,确認序号字段才有效,ack=seq+1。

  (3)标志位:共6個,即URG、ACK、PSH、RST、SYN、FIN等,具體含義如下:

  (A)URG:緊急指針(urgent pointer)有效。

  (B)ACK:确認序号有效。

  (C)PSH:接收方應該盡快将這個封包交給應用層。

  (D)RST:重置連接配接。

  (E)SYN:發起一個新連接配接。

  (F)FIN:釋放一個連接配接。

需要注意的是:

  • 不要将确認序号ack與标志位中的ACK搞混了。
  • 确認方ack=發起方req+1,兩端配對。
TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

第一次握手:

用戶端發送一個TCP的SYN标志位置1的包指明客戶打算連接配接的伺服器的端口,以及初始序号X,儲存在標頭的序列号(Sequence Number)字段裡。

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

第二次握手:

伺服器發回确認包(ACK)應答。即SYN标志位和ACK标志位均為1同時,将确認序号(Acknowledgement Number)設定為客戶的I S N加1以.即X+1。

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

第三次握手.

用戶端再次發送确認包(ACK) SYN标志位為0,ACK标志位為1.并且把伺服器發來ACK的序号字段+1,放在确定字段中發送給對方.并且在資料段放寫ISN的+1

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

為什麼不能隻兩次握手?

有了三次握手的詳細步驟,就可以分析為什麼需要三次握手而不是兩次握手了。

三次握手的目的:消除舊有連接配接請求的SYN消息對新連接配接的幹擾,同步連接配接雙方的序列号和确認号并交換TCP 視窗大小資訊。

設想:如果隻有兩次握手,那麼第二次握手後伺服器隻向用戶端發送ACK包,此時用戶端與伺服器端建立連接配接。

在這種握手規則下: 

假設:如果發送網絡阻塞,由于TCP/IP協定定時重傳機制,B向A發送了兩次SYN請求,分别是x1和x2,且因為阻塞原因,導緻x1連接配接請求和x2連接配接請求的TCP視窗大小和資料封包長度不一緻,如果最終x1達到A,x2丢失,此時A同B建立了x1的連接配接,這個時候,因為AB已經連接配接,B無法知道是請求x1還是請求x2同A連接配接,如果B預設是最近的請求x2同A建立了連接配接,此時B開始向A發送資料,資料封包長度為x2定義的長度,視窗大小為x2定義的大小,而A建立的連接配接是x1,其資料包長度大小為x1,TCP視窗大小為x1定義,這就會導緻A處理資料時出錯。

很顯然,如果A接收到B的請求後,A向B發送SYN請求y3(y3的視窗大小和資料報長度等資訊為x1所定義),确認了連接配接建立的視窗大小和資料報長度為x1所定義,A再次确認回答建立x1連接配接,然後開始互相傳送資料,那麼就不會導緻資料處理出錯了。

SYN攻擊

在三次握手過程中,伺服器發送SYN-ACK之後,收到用戶端的ACK之前的TCP連接配接稱為半連接配接(half-open connect).此時伺服器處于Syn_RECV狀态.當收到ACK後,伺服器轉入SYN_RCVD狀态.

Syn攻擊就是 攻擊用戶端 在短時間内僞造大量不存在的IP位址,向伺服器不斷地發送syn包,伺服器回複确認包,并等待客戶的确認,由于源位址是不存在的,伺服器需要不斷的重發直 至逾時,這些僞造的SYN包将長時間占用未連接配接隊列,正常的SYN請求被丢棄,目标系統運作緩慢,嚴重者引起網絡堵塞甚至系統癱瘓。

Syn攻擊是一個典型的DDOS攻擊。檢測SYN攻擊非常的友善,當你在伺服器上看到大量的半連接配接狀态時,特别是源IP位址是随機的,基本上可以斷定這是一次SYN攻擊.在Linux下可以如下指令檢測是否被Syn攻擊

netstat -n -p TCP | grep SYN_RECV

一般較新的TCP/IP協定棧都對這一過程進行修正來防範Syn攻擊,修改tcp協定實作。主要方法有SynAttackProtect保護機制、SYN cookies技術、增加最大半連接配接和縮短逾時時間等.

但是不能完全防範syn攻擊。

四次揮手

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手
  • 四次揮手即終止TCP連接配接,就是指斷開一個TCP連接配接時,需要用戶端和服務端總共發送4個包以确認連接配接的斷開。在socket程式設計中,這一過程由用戶端或服務端任一方執行close來觸發。
  • 由于TCP連接配接是全雙工的,是以,每個方向都必須要單獨進行關閉,這一原則是當一方完成資料發送任務後,發送一個FIN來終止這一方向的連接配接,收到一個FIN隻是意味着這一方向上沒有資料流動了,即不會再收到資料了,但是在這個TCP連接配接上仍然能夠發送資料,直到這一方向也發送了FIN。首先進行關閉的一方将執行主動關閉,而另一方則執行被動關閉。
  • 中斷連接配接端可以是用戶端,也可以是伺服器端。
  • 第一次揮手:用戶端發送一個FIN=M,用來關閉用戶端到伺服器端的資料傳送,用戶端進入FIN_WAIT_1狀态。意思是說"我用戶端沒有資料要發給你了",但是如果你伺服器端還有資料沒有發送完成,則不必急着關閉連接配接,可以繼續發送資料。
  • 第二次揮手:伺服器端收到FIN後,先發送ack=M+1,告訴用戶端,你的請求我收到了,但是我還沒準備好,請繼續你等我的消息。這個時候用戶端就進入FIN_WAIT_2 狀态,繼續等待伺服器端的FIN封包。
  • 第三次揮手:當伺服器端确定資料已發送完成,則向用戶端發送FIN=N封包,告訴用戶端,好了,我這邊資料發完了,準備好關閉連接配接了。伺服器端進入LAST_ACK狀态。
  • 第四次揮手:用戶端收到FIN=N封包後,就知道可以關閉連接配接了,但是他還是不相信網絡,怕伺服器端不知道要關閉,是以發送ack=N+1後進入TIME_WAIT狀态,如果Server端沒有收到ACK則可以重傳。伺服器端收到ACK後,就知道可以斷開連接配接了。用戶端等待了2MSL後依然沒有收到回複,則證明伺服器端已正常關閉,那好,我用戶端也可以關閉連接配接了。最終完成了四次握手。

需四次揮手原因

由于TCP的半關閉特性,TCP連接配接時雙全工(即資料在兩個方向上能同時傳遞),是以,每個方向必須單獨的進行關閉。這個原則就是:當一方完成它的資料發送任務後就能發送一個FIN來終止這個方向上的連接配接。當一端收到一個FIN後,它必須通知應用層另一端已經終止了那個方向的資料傳送。即收到一個FIN意味着在這一方向上沒有資料流動了。

目的:保證伺服器與用戶端都能完全的接受對方發送的資料。

為什麼TIME_WAIT狀态需要經過2MSL(最大封包段生存時間)才能傳回到CLOSE狀态?

(1)實作TCP全雙工連結的終止。

這是因為雖然雙方都同意關閉連接配接了,而且握手的4個封包也都協調和發送完畢,按理可以直接回到CLOSED狀态(就好比從SYN_SEND狀态到ESTABLISH狀态那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK封包會一定被對方收到,是以對方處于LAST_ACK狀态下的SOCKET可能會因為逾時未收到ACK封包,而重發FIN封包,是以這個TIME_WAIT狀态的作用就是用來重發可能丢失的ACK封包。

 (2)允許老的重複的分節在網絡中消逝。

假 設在12.106.32.254的1500端口和206.168.1.112.219的21端口之間有一個TCP連接配接。我們關閉這個連結,過一段時間後在 相同的IP位址和端口建立另一個連接配接。後一個連結成為前一個的化身。因為它們的IP位址和端口号都相同。TCP必須防止來自某一個連接配接的老的重複分組在連 接已經終止後再現,進而被誤解成屬于同一連結的某一個某一個新的化身。為做到這一點,TCP将不給處于TIME_WAIT狀态的連結發起新的化身。既然 TIME_WAIT狀态的持續時間是MSL的2倍,這就足以讓某個方向上的分組最多存活msl秒即被丢棄,另一個方向上的應答最多存活msl秒也被丢棄。 通過實施這個規則,我們就能保證每成功建立一個TCP連接配接時。來自該連結先前化身的重複分組都已經在網絡中消逝了。

等2MSL就沒問題了嗎?

不是的

TIME_WAIT狀态下發送的ACK丢失,LAST_ACK時刻設定的重傳定時器逾時,發送重傳的FIN,很不幸,這個FIN也丢失,主動關閉方在TIME_WAIT狀态等待2MSL沒收到任何封包段,進入CLOSED狀态,當此時被動關閉方并沒有收到最後的ACK。是以即使要主動關閉方在TIME_WAIT狀态下停留2MSL,也不一定表示四次握手關閉就一定正常完成。

通過序列号與确認應答提高可靠性

  • 在 TCP 中,當發送端的資料到達接收主機時,接收端主機會傳回一個已收到消息的通知。這個消息叫做确認應答(ACK)。當發送端将資料發出之後會等待對端的确認應答。如果有确認應答,說明資料已經成功到達對端。反之,則資料丢失的可能性很大。
  • 在一定時間内沒有等待到确認應答,發送端就可以認為資料已經丢失,并進行重發。由此,即使産生了丢包,仍然能夠保證資料能夠到達對端,實作可靠傳輸。
  • 未收到确認應答并不意味着資料一定丢失。也有可能是資料對方已經收到,隻是傳回的确認應答在途中丢失。這種情況也會導緻發送端誤以為資料沒有到達目的地而重發資料。
  • 此外,也有可能因為一些其他原因導緻确認應答延遲到達,在源主機重發資料以後才到達的情況也屢見不鮮。此時,源主機隻要按照機制重發資料即可。
  • 對于目标主機來說,反複收到相同的資料是不可取的。為了對上層應用提供可靠的傳輸,目标主機必須放棄重複的資料包。為此我們引入了序列号。
  • 序列号是按照順序給發送資料的每一個位元組(8位位元組)都标上号碼的編号。接收端查詢接收資料 TCP 首部中的序列号和資料的長度,将自己下一步應該接收的序列号作為确認應答返送回去。通過序列号和确認應答号,TCP 能夠識别是否已經接收資料,又能夠判斷是否需要接收,進而實作可靠傳輸。
TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

逾時與重傳

對每個連接配接,TCP管理4個不同的定時器:

  • 重傳定時器用于當希望收到另一端的确認。
  • 堅持定時器使視窗大小資訊保持不斷流動。
  • 保活定時器可以檢測到一個空閑連接配接的另一端何時崩潰或重新開機。
  • 2MSL定時器測量一個連接配接處于TIME_WAIT狀态的時間。

TCP在對端ACK逾時後按照一定的時間間隔進行重試,在多次重試仍逾時後最終會放棄并發送一個複位信号。每次重試的時間間隔是一種被稱為指數退避的倍乘關系,直至一個最大值,如重傳間隔每次重傳時增加1倍直至64秒。

TCP逾時與重傳中最重要的部分就是對一個給定連接配接的往返時間(RRT)的測量。由于路由器和網絡流量均會變化,是以我們認為這個時間可能經常會發生變化,TCP應該跟蹤這些變化并相應地改變其逾時時間。

TCP在收到一個失序的封包段時,立即需要産生一個ACK,這個重複的ACK目的在于讓對方知道收到一個失序的封包段。發送端端不知道的ACK是由一個丢失的封包段引起的,還是由于僅僅出現了幾個封包段的重新排序,如果一連串收到3個或3個以上重複ACK,就非常可能是一個封包段丢失了,于是發送端就重傳丢失的資料封包段,而無需等待逾時定時器溢出,這就是快速重傳算法。

以段為機關發送資料

  • 在建立 TCP 連接配接的同時,也可以确定發送資料包的機關,我們也可以稱其為“最大消息長度”(MSS)。最理想的情況是,最大消息長度正好是 IP 中不會被分片處理的最大資料長度。
  • TCP 在傳送大量資料時,是以 MSS 的大小将資料進行分割發送。進行重發時也是以 MSS 為機關。
  • MSS 在三次握手的時候,在兩端主機之間被計算得出。兩端的主機在發出建立連接配接的請求時,會在 TCP 首部中寫入 MSS 選項,告訴對方自己的接口能夠适應的 MSS 的大小。然後會在兩者之間選擇一個較小的值投入使用。

利用視窗控制提高速度

  • TCP 以1個段為機關,每發送一個段進行一次确認應答的處理。這樣的傳輸方式有一個缺點,就是包的往返時間越長通信性能就越低。
  • 為解決這個問題,TCP 引入了視窗這個概念。确認應答不再是以每個分段,而是以更大的機關進行确認,轉發時間将會被大幅地縮短。也就是說,發送端主機,在發送了一個段以後不必要一直等待确認應答,而是繼續發送。如下圖所示:
    TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手
  • 視窗大小就是指無需等待确認應答而可以繼續發送資料的最大值。上圖中視窗大小為4個段。這個機制實作了使用大量的緩沖區,通過對多個段同時進行确認應答的功能。

滑動視窗控制

TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手
  • 上圖中的視窗内的資料即便沒有收到确認應答也可以被發送出去。不過,在整個視窗的确認應答沒有到達之前,如果其中部分資料出現丢包,那麼發送端仍然要負責重傳。為此,發送端主機需要設定緩存保留這些待被重傳的資料,直到收到他們的确認應答。
  • 在滑動視窗以外的部分包括未發送的資料以及已經确認對端已收到的資料。當資料發出後若如期收到确認應答就可以不用再進行重發,此時資料就可以從緩存區清除。
  • 收到确認應答的情況下,将視窗滑動到确認應答中的序列号的位置。這樣可以順序地将多個段同時發送提高通信性能。這種機制也别稱為滑動視窗控制。

視窗控制中的重發控制

在使用視窗控制中, 出現丢包一般分為兩種情況:

  • ① 确認應答未能傳回的情況。在這種情況下,資料已經到達對端,是不需要再進行重發的,如下圖:
TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手
  • ② 某個封包段丢失的情況。接收主機如果收到一個自己應該接收的序列号以外的資料時,會針對目前為止收到資料傳回确認應答。如下圖所示,當某一封包段丢失後,發送端會一直收到序号為1001的确認應答,是以,在視窗比較大,又出現封包段丢失的情況下,同一個序列号的确認應答将會被重複不斷地傳回。而發送端主機如果連續3次收到同一個确認應答,就會将其對應的資料進行重發。這種機制比之前提到的逾時管理更加高效,是以也被稱為高速重發控制。
TCP三向交握與四次揮手及TCP各種細節關于TCP的四層結構TCP三向交握四次揮手

流量控制

TCP使用滑動視窗協定的形式進行流量控制。該協定允許發送方在停止并等待确認前可以連續發送多個分組,可以加速資料的傳輸。

使用TCP的滑動視窗協定時,接收方不必确認每一個收到的分組,ACK是累積的,它們表示接收方已經正确收到了一直到确認序号減1的所有位元組。

在應用程式讀取了TCP緩沖區的資料後,TCP在需要的時候會發送一個ACK,它并不确認任何新資料,隻是用來增加視窗的右邊沿,是以被稱為視窗更新。

滑動視窗的動态性總結如下:

  • 發送方不必範松一個全視窗大小的資料。
  • 來自接收方的一個封包段确認資料并把視窗向右邊滑動。
  • 視窗的大小可以減小,但是視窗的右邊沿卻不能想做移動。
  • 接收方在發送一個ACK前不必等待視窗被填滿。

TCP需要支援一種被稱為慢啟動的算法,該算法通過觀察到新分組進入網絡的速率應該與另一端傳回确認的速率相同而進行工作。慢啟動為發送方的TCP增加了另一個視窗:擁塞視窗,擁塞視窗被初始化為1個封包段,每收到一個ACK,擁塞視窗就增加一個封包段。發送方取擁塞視窗與通告視窗中的最小值作為發送上限。擁塞視窗是發送方使用的流量控制,而通告視窗則是接收方使用的流量控制。

參考以下部落格:

https://www.cnblogs.com/zmlctt/p/3690998.html

https://blog.csdn.net/qq_26811393/article/details/68925870

https://www.jianshu.com/p/9f3e879a4c9c

繼續閱讀