TCP的三次握手和四次揮手

  TCP協議屬於可靠的傳輸層協議,提供可靠的字節流服務,採用三次握手確認建立一個連接。
  所謂字節流服務(Byte Stream Service)是指,爲了方便傳輸,將大塊數據分割成以報文段(segment)爲單位的數據包進行管理。而可靠的傳輸服務是指,能夠把數據準確可靠的傳送給對方。
  爲了準確無誤的將數據送達目標處,TCP協議採用了三次握手(three-way handshaking)和四次揮手(four-way handshake)策略。用TCP協議把數據包送出去後,TCP協議會向對方確認是否成功送達。

三次握手(建立連接)

  握手過程中使用了TCP的標誌(flag)——SYN(synchronize,同步)和ACK(acknowledge,確認)。
  發送端首先發送一個帶SYN標誌的數據包給對方。接收端收到後,回傳一個帶有SYN/ACK標誌的數據包以示傳達確認信息。最後,發送端再回傳一個帶ACK標誌的數據包,代表“握手”結束。
  下面用一個簡圖先建立一下概念:
  這裏寫圖片描述
  只是瞭解TCP三次握手的概念,是沒有卵用的,你需要去了解TCP三次握手中的一些細節,來看一個詳細的圖。 
  位碼即TCP標誌位,有6種標示
  SYN(synchronize建立聯機)
  ACK(acknowledgement確認)
  PSH(push傳送)
  FIN(finish結束)
  URG(urgent緊急)
  Sequence number(順序號碼)
  Acknowledge number(確認號碼)
  這裏寫圖片描述
  各個狀態的意義如下:
  LISTEN-偵聽來自遠方TCP端口的連接請求;
  SYN_SENT-在發送連接請求後等待匹配的連接請求;
  SYN_RECEVED-在收到和發送一個連接請求後等待對連接請求的確認;
  ESTABLISHED-代表一個打開的連接,數據可以傳送給用戶;
  
  第一次握手:建立連接。客戶端發送連接請求報文段,將SYN位置爲1,Sequence Number爲x;然後,客戶端進入SYN_SEND狀態,等待服務器的確認;
  第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgement Numberx+1(Sequence Number+1);同時,自己還要發送SYN請求信息,將SYN位置爲1,Sequence Numbery;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時服務器進入SYN_RECV狀態;
  第三次握手:客戶端收到服務器的SYN+ACK報文段。然後將Acknowledgment Number設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢以後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。

  完成了三次握手,客戶端和服務器端就可以開始傳送數據。

  確認號:其數值等於發送方的發送序號 +1(即接收方期望接收的下一個序列號)。

四次揮手(斷開連接)

  由於TCP連接是全雙工的,一個TCP連接存在雙向的讀寫通道,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP連接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
  簡單說來是 “先關讀,後關寫”,一共需要四個階段。以客戶機發起關閉連接爲例:

1.服務器讀通道關閉
2.客戶機寫通道關閉
3.客戶機讀通道關閉
4.服務器寫通道關閉

  關閉行爲是在發起方數據發送完畢之後,給對方發出一個FIN(finish)數據段。直到接收到對方發送的FIN,且對方收到了接收確認ACK之後,雙方的數據通信完全結束,過程中每次接收都需要返回確認數據段ACK。
詳細過程:
  第一階段 客戶機發送完數據之後,向服務器發送一個FIN數據段,序列號爲i
  1.服務器收到FIN(i)後,返回確認段ACK,序列號爲i+1,關閉服務器讀通道;
  2.客戶機收到ACK(i+1)後,關閉客戶機寫通道;
(此時,客戶機仍能通過讀通道讀取服務器的數據,服務器仍能通過寫通道寫數據)
  第二階段 服務器發送完數據之後,向客戶機發送一個FIN數據段,序列號爲j;
  3.客戶機收到FIN(j)後,返回確認段ACK,序列號爲j+1,關閉客戶機讀通道;
  4.服務器收到ACK(j+1)後,關閉服務器寫通道。
  這是標準的TCP關閉兩個階段,服務器和客戶機都可以發起關閉,完全對稱。

爲什麼握手是三次

  那TCP爲什麼非要進行三次連接呢?在謝希仁的《計算機網絡》中是這樣說的:

爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤。

  在書中同時舉了一個例子,如下:

“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認爲是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不採用“三次握手”,那麼只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以爲新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。採用“三次握手”的辦法可以防止上述現象發生。例如剛纔那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。

  這就很明白了,防止了服務器端的一直等待而浪費資源。

揮手爲什麼是四次

  那四次分手又是爲何呢?TCP協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。TCP是全雙工模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之後彼此就會愉快的中斷這次TCP連接。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態變化。
  

  • FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)
  • FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你(ACK信息),稍後再關閉連接。(主動方)
  • CLOSE_WAIT:這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。(被動方)
  • LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。(被動方)
  • TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)
  • CLOSED: 表示連接中斷。
發佈了116 篇原創文章 · 獲贊 132 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章