1. 程式人生 > >TCP協議的三次握手和四次揮手(詳細圖解)

TCP協議的三次握手和四次揮手(詳細圖解)

TCP的概述

TCP把連線作為最基本的物件,每一條TCP連線都有兩個端點,這種斷點我們叫作套接字(socket),它的定義為埠號拼接到IP地址即構成了套接字,例如,若IP地址為192.3.4.16 而埠號為80,那麼得到的套接字為192.3.4.16:80。

 TCP報文首部

  1. 源埠和目的埠,各佔2個位元組,分別寫入源埠和目的埠;
  2. 序號,佔4個位元組,TCP連線中傳送的位元組流中的每個位元組都按順序編號。例如,一段報文的序號欄位值是 301 ,而攜帶的資料共有100欄位,顯然下一個報文段(如果還有的話)的資料序號應該從401開始;
  3. 確認號,佔4個位元組,是期望收到對方下一個報文的第一個資料位元組的序號。例如,B收到了A傳送過來的報文,其序列號欄位是501,而資料長度是200位元組,這表明B正確的收到了A傳送的到序號700為止的資料。因此,B期望收到A的下一個資料序號是701,於是B在傳送給A的確認報文段中把確認號置為701;
  4. 資料偏移,佔4位,它指出TCP報文的資料距離TCP報文段的起始處有多遠;
  5. 保留,佔6位,保留今後使用,但目前應都位0;
  6. 緊急URG,當URG=1,表明緊急指標欄位有效。告訴系統此報文段中有緊急資料;
  7. 確認ACK,僅當ACK=1時,確認號欄位才有效。TCP規定,在連線建立後所有報文的傳輸都必須把ACK置1;
  8. 推送PSH,當兩個應用程序進行互動式通訊時,有時在一端的應用程序希望在鍵入一個命令後立即就能收到對方的響應,這時候就將PSH=1;
  9. 復位RST,當RST=1,表明TCP連線中出現嚴重差錯,必須釋放連線,然後再重新建立連線;
  10. 同步SYN,在連線建立時用來同步序號。當SYN=1,ACK=0,表明是連線請求報文,若同意連線,則響應報文中應該使SYN=1,ACK=1;
  11. 終止FIN,用來釋放連線。當FIN=1,表明此報文的傳送方的資料已經發送完畢,並且要求釋放;
  12. 視窗,佔2位元組,指的是通知接收方,傳送本報文你需要有多大的空間來接受;
  13. 檢驗和,佔2位元組,校驗首部和資料這兩部分;
  14. 緊急指標,佔2位元組,指出本報文段中的緊急資料的位元組數;
  15. 選項,長度可變,定義一些其他的可選的引數。

TCP連線的建立(三次握手)

先附上TCP連線的圖吧,然後拿圖來分析:

  1. 伺服器先建立傳輸控制塊TCB,然後伺服器進入監聽階段
  2. (第一次握手)客戶端建立傳輸控制塊TCB,然後傳送一個請求連線SYN(SYN=1是請求連線)以及自己的序號seq,假設seq是x,傳送完畢後客戶端進入SYN-SENT(同步已傳送)階段
  3. (第二次握手)當伺服器收到客戶端傳送的一個連線請求後,伺服器傳送一個確認收到的ACK(ACK=1表示自己已經收到)已經一個確認號(期望下一次收到的序號)ack=x+1,一個請求連線SYN已經自己的一個序號seq=y
  4. (第三次握手)當客戶端收到服務的確認之後,給伺服器傳送一個確認ACK,一個確認號ack=y+1以及自己的一個序號seq=x+1
  5. 客戶端與伺服器的連線建立成功,開始資料傳輸

為什麼TCP的連線需要建立三次握手麼?不能建立兩次握手呢?

假設TCP連線只是建立兩次握手的話,那麼當第二次握手的時候伺服器給客戶端傳輸報文的途中突然鏈路堵塞了,這時候客戶端沒有收到伺服器的一個確認資料報,我們都知道TCP有一個超時重傳機制,客戶端會再次請求伺服器傳送確認資料報,當客戶端收到以後會跟伺服器建立連線,但是之後鏈路又可以通行了,客戶端突然收到伺服器傳來的一個確認資料報,這時候他會再次建立連線,這時候就會浪費資源.

而我們說的三次握手則不會產生這種現象,仔細分析一下,如果伺服器在給客戶端傳輸確認資料報的時候鏈路堵塞了,重傳,客戶端收到後會給伺服器傳送一個ACK和一個確認號ack=y+1已經自己的一個seq=x+1,如果這時候收到鏈路堵塞時伺服器傳給客戶端的資料報,由於確認號與預期的不一樣,預期ack=x+2,堵塞ack=x+1,所以客戶端不會理會這一段確認資料報,直接丟棄.這樣就不會出現連接出現兩次而出現資源浪費的情況.

 附上一個動圖(有助於理解)

 


TCP連線的釋放(四次揮手)

老規矩先附上TCP連線釋放的圖,然後拿圖來分析:

  1. (第一次揮手)由客戶端先發送一個FIN(FIN=1請求釋放連線),以及自己的一個序號seq=u(這時候客戶端已經不能向伺服器端傳送其他資料了)
  2. (第二次揮手)當伺服器收到客戶端的一個關閉請求之後,會發送一個確認ACK,以及一個確認號ack=u+1和自己的序號seq=v
  3. 當伺服器給客戶端傳送完確認ACK後,伺服器還是能向客戶端傳輸資料的,客戶端雖然不能傳送資料但是還是能接受資料的
  4. (第三次揮手)當伺服器把剩餘的資料傳送完之後,就向伺服器端傳送一個FIN,以及自己的一個seq=w(假設剛剛伺服器端又向客戶端傳送了一些資料),以及一個確認號ack=u+1
  5. (第四次揮手)當客戶端收到伺服器端傳送後客戶端會發送一個確認ACK,ack=w+1以及自己的一個序號u+1,客戶端需要等待2MSL然後再關閉
  6. 當伺服器收到客戶端的一個確認ACK後,伺服器會立馬關閉,

 附上動圖,更好理解:

為什麼第四次揮手,伺服器收到客戶端的確認ACK,伺服器會立馬關閉而客戶端為什麼不是傳送之後直接斷開連線而會等待2MSL才關閉呢?

假設客戶端在傳送ACK後直接關閉,如果確認號在中途丟失,伺服器沒有接受到,根據TCP的確認重傳機制,伺服器會再次傳送一個釋放連線的FIN,而這時候客戶端已經關閉了,那麼伺服器端就關閉不了了

若客戶端在2MSL後關閉則不會出現這個問題,如果客戶端的確認資料報在途中丟失,在2MSL內伺服器會再次向客戶端傳送一個釋放連線的FIN,客戶端在收到收到這個資料報後又會重啟計時器,就解決了這個問題


為什麼TCP建立連線是三次握手而釋放連線卻是四次揮手呢?

因為TCP是全雙工通訊,在客戶端主動發起釋放連線的請求後,只能說客戶端已經完成了所以的資料傳輸,而不再發送資料了,但是還是可以接受資料的,而伺服器端傳送ACK後直接關閉是不行的,因為伺服器端還有可能些資料沒有傳送完的,所以伺服器在傳送確認ACK之後可能會傳輸剩餘的資料給客戶端再發送釋放連線FIN。

 參考部落格