TCP的三次握手和四次揮手理解,附帶常見面試題

本文部分內容借鑑別人博客加以理解總結,不足之處歡迎指正!!!

1、TCP介紹

講TCP之前必須先說一下TCP/IP協議,TCP/IP 意味着 TCP 和 IP 在一起協同工作。
TCP 負責不同應用程序之間的通信。IP負責兩臺設備之間的通信。
TCP 負責將數據分割並裝入 IP 包,然後在它們到達的時候重新組合它們。IP 負責將包發送至接受者。
TCP/IP不是一個協議,而是一個協議族的統稱,包括了IP協議,IMCP協議,TCP協議,以及我們更加熟悉的http、ftp、pop3協議等等。

IP協議雖然能把數據報文送到目的主機,但是並沒有交付給主機的具體應用進程。而端到端的通信才應該是應用進程之間的通信。此時就需要用到UDP和TCP。

UDP,在傳送數據前不需要先建立連接,遠地的主機在收到UDP報文後也不需要給出任何確認。雖然UDP不提供可靠交付,但是正是因爲這樣,省去和很多的開銷,使得它的速度比較快,比如一些對實時性要求較高的服務,就常常使用的是UDP。對應的應用層的協議主要有DNS,TFTP,DHCP,SNMP,NFS 等

TCP,提供面向連接的服務,在傳送數據之前必須先建立連接,數據傳送完成後要釋放連接。因此TCP是一種可靠的的運輸服務,但是正因爲這樣,不可避免的增加了許多的開銷,比如確認,流量控制等。對應的應用層的協議主要有SMTP,TELNET,HTTP,FTP 等。

2、TCP/IP協議分層

在這裏插入圖片描述

  • 應用層:
    向用戶提供一組常用的應用程序,比如電子郵件、文件傳輸訪問、遠程登錄等。遠程登錄TELNET使用TELNET協議提供在網絡其它主機上註冊的接口。TELNET會話提供了基於字符的虛擬終端。文件傳輸訪問FTP使用FTP協議來提供網絡內機器間的文件拷貝功能。

  • 傳輸層:
    提供應用程序間的通信。其功能包括:一、格式化信息流;二、提供可靠傳輸。爲實現後者,傳輸層協議規定接收端必須發回確認,並且假如分組丟失,必須重新發送。

  • 網絡層 :
    負責相鄰計算機之間的通信。其功能包括三方面。

    1. 處理來自傳輸層的分組發送請求,收到請求後,將分組裝入IP數據報,填充報頭,選擇去往信宿機的路徑,然後將數據報發往適當的網絡接口。
    2. 處理輸入數據報:首先檢查其合法性,然後進行尋徑–假如該數據報已到達信宿機,則去掉報頭,將剩下部分交給適當的傳輸協議;假如該數據報尚未到達信宿,則轉發該數據報。
    3. 處理路徑、流控、擁塞等問題。
  • 網絡接口層:
    這是TCP/IP軟件的最低層,負責接收IP數據報並通過網絡發送之,或者從網絡上接收物理幀,抽出IP數據報,交給IP層。

3、 TCP的報文格式

在這裏插入圖片描述

  1. 源端口,16比特,標識哪個應用程序發送。
  2. 目的端口,16比特,標識哪個應用程序接收。
  3. 序號字段。32比特,TCP鏈接中傳輸的數據流中每個字節都編上一個序號。序號字段的值指的是本報文段所發送的數據的第一個字節的序號。
  4. 確認號,32比特,是期望收到對方的下一個報文段的數據的第1個字節的序號,即上次已成功接收到的數據字節序號加1。只有ACK標識爲1,此字段有效。
  5. 數據偏移,4比特。即首部長度,指出TCP報文段的數據起始處距離TCP報文段的起始處有多遠,以32比特(4字節)爲計算單位。最多有60字節的首部,若無選項字段,正常爲20字節。
  6. 保留,6比特,必須填0。
  7. URG:緊急指針有效標識。1比特,它告訴系統此報文段中有緊急數據,應儘快傳送(相當於高優先級的數據),緊急標誌爲"1"表明該位有效。
  8. ACK:確認序號有效標識。 1比特,只有當ACK=1時確認號字段纔有效。當ACK=0時,確認號無效。大多數情況下該標誌位是置位的。TCP報頭內的確認編號欄內包含的確認編號(w+1)爲下一個預期的序列編號,同時提示遠端系統已經成功接收所有數據。
  9. PSH :標識接收方應該儘快將這個報文段交給應用層,1比特。接收到PSH = 1的TCP報文段,應儘快的交付接收應用進程,而不再等待整個緩存都填滿了後再向上交付。
  10. RST,1比特,重建連接標識。 當RST=1時,表明TCP連接中出現嚴重錯誤(如由於主機崩潰或其他原因),必須釋放連接,然後再重新建立連接。
  11. SYN,1比特,同步序號標識,用來發起一個連接。 SYN=1表示這是一個連接請求或連接接受請求。該標誌僅在三次握手建立TCP連接時有效。它提示TCP連接的服務端檢查序列編號,該序列編號爲TCP連接初始端(一般是客戶端)的初始序列編號。在這裏,可以把TCP序列編號看作是一個範圍從0到4,294,967,295的32位計數器。通過TCP連接交換的數據中每一個字節都經過序列編號。在TCP報頭中的序列編號欄包括了TCP分段中第一個字節的序列編號。
  12. FIN,1比特,發端完成發送任務標識。 用來釋放一個連接。FIN=1表明此報文段的發送端的數據已經發送完畢,並要求釋放連接。
  13. 窗口, 16比特:TCP的流量控制,窗口起始於確認序號字段指明的值,這個值是接收端正期望接收的字節數。窗口最大爲65535字節。
  14. 校驗字段,16比特,包括TCP首部和TCP數據,是一個強制性的字段,一定是由發端計算和存儲,並由收端進行驗證。在計算檢驗和時,要在TCP報文段的前面加上12字節的僞首部。
  15. 緊急指針,16比特,只有當URG標誌置1時緊急指針纔有效。TCP的緊急方式是發送端向另一端發送緊急數據的一種方式。緊急指針指出在本報文段中緊急數據共有多少個字節(緊急數據放在本報文段數據的最前面)。
  16. 選項字段,可變。TCP協議最初只規定了一種選項,即最長報文段長度(數據字段加上TCP首部),又稱爲MSS。MSS告訴對方TCP“我的緩存所能接收的報文段的數據字段的最大長度是MSS個字節”。
    新的RFC規定有以下幾種選型:選項表結束,無操作,最大報文段長度,窗口擴大因子,時間戳。
    • 窗口擴大因子:3字節,其中一個字節表示偏移值S。新的窗口值等於TCP首部中的窗口位數增大到(16+S),相當於把窗口值向左移動S位後獲得實際的窗口大小。
    • 時間戳:10字節,其中最主要的字段是時間戳值(4字節)和時間戳回送應答字段(4字節)。
    • 選項確認選項:
  17. 填充字段,可變,用來補位,使整個首部長度是4字節的整數倍。
  18. 數據部分,可變,TCP負載。

4、三次握手

在這裏插入圖片描述

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

5、四次揮手

四次揮手(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狀態,完成四次揮手。

四次揮手的狀態
FIN_WAIT_1: 這個狀態和FIN_WAIT_2狀態都在再等待對方的回覆,但是這兩種狀態是有區別的,FIN_WAIT_1就是主動方在ESTABLISHED狀態的時候,想要主動關閉連接,向對方發送FIN報文,這時候就進入了FIN_WAIT_1狀態。當他收到對方回覆的ACK報文後,就進入了FIN_WAIT_2狀態。 但是在實際操作中是很難遇到FIN_WAIT_1狀態的,因爲無論對方是什麼情況都應該立刻迴應ACK報文,但是FIN_WAIT_2狀態還是可以在主動方中用netstat看到的。

FIN_WAIT_2: 上面已經對FIN_WAIT_2講解過了,當主動方進入FIN_WAIT_2時,就表示着半連接狀態,也就是主動方還有數據要發給對方,這個數據就是之後的ACK,所有他要等一會兒才關閉連接。

CLOSE_WAIT: 這個狀態從表面也可以看出它的作用,就是等待關閉。當被動方接收到FIN時,會立刻回覆一個ACK給對方,接下來就是進入CLOSE_WAIT狀態。在這個狀態中,被動方需要考慮自己還有沒有數據要發送給對方,如果有可以繼續發送,如果沒有了就可以關閉連接了,發送一個FIN給對方。 這個狀態其實也就是給自己一個緩衝的時間,讓自己處理完需要處理的事,然後去關閉連接。

TIME_WAIT: 這個狀態就是一段時間後進行一些操作。當主動方收到了對方發來的FIN報文,併發出ACK報文,接下來就等2MSL就可以進入CLOSED狀態了。其實,如果主動方在FIN_WAIT_1狀態下,收到了對方的FIN+ACK標誌的報文,就可以跳過FIN_WAIT_2狀態直接進入TIME_WAIT狀態了。

LAST_ACK: 這個狀態從表面不難不理解他的意思,這個狀態就是被動方發送了FIN報文後,最後等待對方的ACK報文,收到ACK報文後就可以進入CLOSED狀態了。

CLOSED: 上面提到了幾次這個狀態,相比也猜出來了,這個狀態表示的就是連接中斷,已經關閉。

6、常見面試題

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

  • a、保證TCP協議的全雙工連接能夠可靠關閉
    如果Client直接CLOSED了,那麼由於IP協議的不可靠性或者是其它網絡原因,導致Server沒有收到Client最後回覆的ACK。那麼Server就會在超時之後繼續發送FIN,此時由於Client已經CLOSED了,就找不到與重發的FIN對應的連接,最後Server就會收到RST而不是ACK,Server就會以爲是連接錯誤把問題報告給高層。這樣的情況雖然不會造成數據丟失,但是卻導致TCP協議不符合可靠連接的要求。所以,Client不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,能夠保證對方收到ACK,最後正確的關閉連接。
  • b、保證這次連接的重複數據段從網絡中消失
    如果Client直接CLOSED,然後又再向Server發起一個新連接,我們不能保證這個新連接與剛關閉的連接的端口號是不同的。也就是說有可能新連接和老連接的端口號是相同的。一般來說不會發生什麼問題,但是還是有特殊情況出現:假設新連接和已經關閉的老連接端口號是一樣的,如果前一次連接的某些數據仍然滯留在網絡中,這些延遲數據在建立新連接之後纔到達Server,由於新連接和老連接的端口號是一樣的,又因爲TCP協議判斷不同連接的依據是socket pair,於是,TCP協議就認爲那個延遲的數據是屬於新連接的,這樣就和真正的新連接的數據包發生混淆了。所以TCP連接還要在TIME_WAIT狀態等待2倍MSL,這樣可以保證本次連接的所有數據都從網絡中消失。

②、爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?

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

③、爲什麼不能用兩次握手進行連接?

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

④、如果連接已經建立,但是客戶端突然出現故障了怎麼辦?

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

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