說說TCP的三次握手和四次揮手

一、傳輸控制協議TCP簡介

1.1 簡介

TCP(Transmission Control Protocol) 傳輸控制協議,是一種 面向連接的、可靠的、基於字節流的傳輸層 通信協議。

TCP是一種面向連接(連接導向)的、可靠的基於字節流的傳輸層通信協議。TCP將用戶數據打包成報文段,它發送后啟動一個定時器,另一端收到的數據進行確認、對失序的數據重新排序、丟棄重複數據。

TCP把連接作為最基本的對象,每一條TCP連接都有兩個端點,這種端點我們叫作套接字(socket),將端口號拼接到IP地址即構成了套接字,例如 192.1.1.6:50030

1.2 特點

  • 面向連接的、可靠的、基於字節流的 傳輸層 通信協議
  • 將應用層的數據流分割成文段併發送給目標節點的TCP層
  • 數據包都有序號,對方收到則發送ACK確認,未收到則重傳
  • 使用校驗和來檢驗數據在傳輸過程中是否有誤

二、TCP報文頭

1、源端口(Source Port)/ 目的端口(Destination Port):他們各佔2個字節,標示該段報文來自哪裡(源端口)以及要傳給哪個上層協議或應用程序(目的端口)。進行tcp通信時,一般client是通過系統自動選擇的臨時端口號,而服務器一般是使用知名服務端口號或者自己指定的端口號(比如DNS協議對應端口53,HTTP協議對應80)

2、序號(Sequence Number):佔據四個字節,TCP是面向字節流的,TCP連接中傳送的字節流中的每個字節都按順序編號,例如如一段報文的序號字段值是107,而攜帶的數據共有100個字段,如果有下一個報文過來,那麼序號就從207(100+107)開始,整個要傳送的字節流的起始序號必須要在連接建立時設置。首部中的序號字段值指的是本報文段所發送的數據的第一個字節的序號

3、確認序號(Acknowledgment Number):4個字節,是期望收到對方下一個報文段的第一個數據字節的序號,若確認號=N,則表明:到序號N-1為止的所有數據都已正確收到,例如:B收到A發送過來的報文,其序列號字段是301,而數據長度是200字節,這表明了B正確的收到了A到序號500(301+200-1)為止的數據,因此B希望收到A的下一個數據序號是501,於是B在發送給A的確認報文段中,會把ACK確認號設置為501

4、數據偏移(Offset):4個字節。指出TCP報文段的數據起始處距離報文段的起始處有多遠,這個字段實際上是指出TCP報文段的首部長度。由於首部中還有長度不確定的選項字段,因此數據偏移字段是必要的。單位是32位字,也就是4字節,4位二進制最大表示15,所以數據偏移也就是TCP首部最大60字節

5、保留(Reserved):6個字節。保留域

6、TCP Flags:控制位,由八個標誌位組成,每個標誌位表示控制的功能,我們主要來介紹TCP Flags中常用的六個,

  • URG(緊急指針標誌):當URG=1時,表明緊急指針字段有效。它告訴系統此報文段中有緊急數據,應儘快傳送(相當於高優先級的數據),而不要按原來的排隊順序來傳送。例如,已經發送了很長的一個程序在主機上運行。但後來發現了一些問題,需要取消該程序的運行。因此用戶從鍵盤發出中斷命令。如果不使用緊急數據,那麼這兩個字符將存儲在接收TCP的緩存末尾。只有在所有的數據被處理完畢后這兩個字符才被交付接收方的應用進程。這樣做就浪費了許多時間

  • ACK(確認序號標誌):當ACK=1時確認號字段有效。當ACK=0時,確認號無效。TCP規定,在連接建立后所有的傳送的報文段都必須把ACK置1

  • PSH(push標誌):當兩個應用進程進行交互式的通信時,有時在一端的應用進程希望在鍵入一個命令后立即就能收到對方的響應。在這種情況下,TCP就可以使用推送操作。這時,發送方TCP把PSH置1,並立即創建一個報文段發送出去。接收方TCP收到PSH=1的報文段,就儘快地交付接收應用進程,而不再等到整個緩存都填滿了後向上交付

  • RST(重置連接標誌):TCP連接中出現嚴重差錯(如由於主機崩潰或其他原因),必須釋放連接,然後再重新建立運輸連接,可以用來拒絕一個非法的報文段或拒絕打開一個連接

  • SYN(同步序號,用於建立連接過程):在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文段。對方若同意建立連接,則應在相應的報文段中使用SYN=1和ACK=1。因此,SYN置為1就表示這是一個連接請求或連接接受保溫。

  • FIN(finish標誌,用於釋放連接):當FIN=1時,表明此報文段的發送方的數據已發送完畢,並要求釋放運輸連接

7、窗口(Window)是TCP流量控制的一個手段。這裏說的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告訴對方本端的TCP接收緩衝區還能容納多少字節的數據,這樣就可以控制發送數據的速度

8、檢驗和(Checksum):檢驗範圍包括首部和數據兩部分,由發送端填充,接收端對TCP報文段執行CRC算法以檢驗TCP報文段在傳輸過程中是否損壞。這也是TCP可靠傳輸的一個重要保障

9、緊急指針(Urgent Pointer):緊急指針僅在URG=1時才有意義,它指出本報文段中的緊急數據的字節數(緊急數據結束后就是普通數據)。因此,緊急指針指出了緊急數據的末尾在報文段中的位置。當所有緊急數據都處理完時,TCP就告訴應用程序恢復到正常操作。值得注意的是,即使窗口為零時也可發送緊急數據。

10、TCP可選項(TCP Options):長度可變,最長可達40字節。當沒有使用“選項”時,TCP的首部長度是20字節。

三、TCP的三次握手

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。在socket編程中,這一過程由客戶端執行connect來觸發,整個流程如下圖所示:

在TCP/IP協議中,TCP協議提供可靠的連接服務,採用三次握手建立一個連接。

第一次握手: 建立連接時,客戶端發送SYN包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認,SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手: 服務器收到 SYN 包,必須確認客戶的 SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

第三次握手: 客戶端收到服務器的SYN + ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。

3.1 為什麼需要三次握手才能建立連接

  • 為了初始化Sequence Number 的初始值,實現可靠數據傳輸, TCP 協議的通信雙方, 都必須維護一個序列號, 以標識發送出去的數據包中, 哪些是已經被對方收到的。 三次握手的過程即是通信雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟
  • 如果只是兩次握手, 至多只有連接發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認

3.2 首次握手的隱患——SYN超時

一、問題起因分析:
  1. 服務器收到客戶端的SYN,回復SYN和ACK的時候未收到ACK確認
  2. 服務器不斷重試直至超時,Linux默認等待63秒才斷開連接;(重複5次【不包括第一次】,從1秒開始,每次重試都翻倍:1+2+4+8+16+32=63秒)
二、針對SYN Flood的防護措施:
  1. SYN隊列滿后,通過tcp_syncookies參數會發SYN cookie【源端口+目標端口+時間戳組成】
  2. 若為正常連接則Client會回發SYN Cookie,直接建立連接;

3.3 保活機制:

當我們建立連接后,Client出現故障怎麼辦?

  1. 向對方發送保活探測報文,如果未收到響應則繼續發送;
  2. 嘗試次數達到保活探測數仍未收到相應則中斷連接;

四、TCP的四次揮手

所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發,整個流程如下圖所示:

由於TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務后,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

  • 第一次揮手: Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態
  • 第二次揮手: Server收到FIN后,發送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態
  • 第三次揮手: Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態
  • 第四次揮手: Client收到FIN后,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態,完成四次揮手
一、為什麼會有TIME_WAIT狀態

客戶端連接在收到服務器的結束報文段之後,不會直接進入CLOSED狀態,而是轉移到TIME_WAIT狀態。在這個狀態,客戶端連接要等待一段長為2MSL,即兩倍的報文段最大生存時間,才能完全關閉,其原因主要有兩點:

  • 確保有足夠的時間放對方收到ACK包
  • 避免新舊連接混淆
二、為什麼需要四次握手才能斷開連接

因為TCP連接是全雙工的網絡協議,允許同時通信的雙方同時進行數據的收發,同樣也允許收發兩個方向的連接被獨立關閉,以避免client數據發送完畢,向server發送FIN關閉連接,而server還有發送到client的數據沒有發送完畢的情況。所以關閉TCP連接需要進行四次握手,每次關閉一個方向上的連接需要FIN和ACK兩次握手,發送發和接收方都需要FIN報文和ACK報文

三、服務器出現大量CLOSE_WAIT狀態的原因

是由於對方關閉socket連接,我方忙於讀或寫,沒有及時關閉連接

當客戶端因為某種原因先於服務端發出了FIN信號,就會導致服務端被動關閉,若服務端不主動關閉socket發FIN給Client,此時服務端Socket會處於CLOSE_WAIT狀態(而不是LAST_ACK狀態)。通常來說,一個CLOSE_WAIT會維持至少2個小時的時間(系統默認超時時間的是7200秒,也就是2小時)。如果服務端程序因某個原因導致系統造成一堆CLOSE_WAIT消耗資源,那麼通常是等不到釋放那一刻,系統就已崩潰

解決:
1、檢查代碼,特別是釋放資源的代碼
2、檢查配置,特別是處理請求的線程配置

Linux的檢查代碼:netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'

五、總結

到這裏TCP的三次握手四次揮手就講完了,好久都沒有寫技術文章了,寫了一下,感覺還挺好的,上面是博主的認識,有寫的不好的地方,大家可以在評論區討論或者提問,博主看到了會第一時間回復大家,最近也準備開始面試了,先好好準備一下,希望今年可以找到心滿意足的工作,也希望今年面試的小夥伴們都有一個好的office,大家一起加油,我是牧小農,我喂自己帶鹽,大家加油。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準