天天看點

漫畫:一招學會TCP的三次握手和四次揮手

漫畫:一招學會TCP的三次握手和四次揮手
TCP三向交握和四次揮手的問題在面試中是最為常見的考點之一。很多讀者都知道三次和四次,但是如果問深入一點,他們往往都無法作出準确回答。

本篇嘗試使用動畫來對這個知識點進行講解,期望讀者們可以更加簡單地地了解TCP互動的本質。

漫畫:一招學會TCP的三次握手和四次揮手

TCP/IP代表傳輸控制協定/網際協定,指的是一系列協組。

可分為四個層次:

  • 1、資料鍊路層、網絡層、傳輸層和應用層。
  • 2、 在網絡層:有IP協定、ICMP協定、ARP協定、RARP協定和BOOTP協定。
  • 3、在傳輸層:中有TCP協定與UDP協定。
  • 4、在應用層:有FTP、HTTP、TELNET、SMTP、DNS等協定。

TCP和UDP使用IP協定從一個網絡傳送資料包到另一個網絡。把IP想像成一種高速公路,它允許其它協定在上面行駛并找到到其它電腦的出口。TCP和UDP是高速公路上的“卡車”,它們攜帶的貨物就是像HTTP,檔案傳輸協定FTP這樣的協定等。

TCP和UDP是FTP,HTTP和SMTP之類使用的傳輸層協定。雖然TCP和UDP都是用來傳輸其他協定的,它們卻有一個顯著的不同:TCP提供有保證的資料傳輸,而UDP不提供。這意味着TCP有一個特殊的機制來確定資料安全的不出錯的從一個端點傳到另一個端點,而UDP不提供任何這樣的保證。

TCP 三次握手

TCP 三次握手就好比兩個人在街上隔着50米看見了對方,但是因為霧霾等原因不能100%确認,是以要通過招手的方式互相确定對方是否認識自己。

漫畫:一招學會TCP的三次握手和四次揮手

互相擁抱

漫畫:一招學會TCP的三次握手和四次揮手

我們看到這個過程中一共是四個動作,招手–點頭微笑–招手–點頭微笑。其中連續進行了2個動作,先是點頭微笑(回複對方),然後再次招手(尋求确認),實際上可以将這兩個動作合一,招手的同時點頭和微笑(syn+ack)。于是四個動作就簡化成了三個動作,招手–點頭微笑并招手–點頭微笑。這就是三次握手的本質,中間的一次動作是兩個動作的合并。

我們看到有兩個中間狀态,syn_sent和syn_rcvd,這兩個狀态叫着「半打開」狀态,就是向對方招手了,但是還沒來得及看到對方的點頭微笑。syn_sent是主動打開方的「半打開」狀态,syn_rcvd是被動打開方的「半打開」狀态。用戶端是主動打開方,伺服器是被動打開方。

  • syn_sent: syn package has been sent
  • syn_rcvd: syn package has been received

TCP 資料傳輸

TCP 資料傳輸就是兩個人隔空對話,差了一點距離,是以需要對方反複确認聽見了自己的話。

漫畫:一招學會TCP的三次握手和四次揮手

用戶端喊了一句話(data),接收方聽見了之後要回複自己聽見了(ack)。

如果喊了一句,半天沒聽到對方回複,就認為自己的話被大風吹走了,沒聽見,是以需要重新喊話,這就是tcp重傳。

也有可能是服務端聽到了用戶端的話,但是Server向Client的回複被大風吹走了,以至于Client沒聽見Server的回複。Client并不能判斷究竟是自己的話被大風吹走了還是Server的回複被大風吹走了,Client也不用管,重傳一下就是。

漫畫:一招學會TCP的三次握手和四次揮手

Client可以向Server喊話,同樣Server也可以向Client喊話,因為tcp連結是「雙工的」,雙方都可以主動發起資料傳輸。不過無論是哪方喊話,都需要收到對方的确認才能認為對方收到了自己的喊話。

Client可能是個高射炮,一說連說了八句話,這時候Server可以不用一句一句回複,而是連續聽了這八句話之後,一起向對方回複說前面你說的八句話我都聽見了,這就是批量ack。但是Client也不能一次性說了太多話,Server的腦子短時間可能無法消化太多,兩人之間需要有協商好的合适的發送和接受速率,這個就是「TCP視窗大小」。

TCP三次連接配接總結

(1) 第一次握手:建立連接配接時,用戶端A發送SYN包(SYN=j)到伺服器B,并進入SYN_SEND狀态,等待伺服器B确認。

(2) 第二次握手:伺服器B收到SYN包,必須确認客戶A的SYN(ACK=j+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時伺服器B進入SYN_RECV狀态。

(3) 第三次握手:用戶端A收到伺服器B的SYN+ACK包,向伺服器B發送确認包ACK(ACK=k+1),此包發送完畢,用戶端A和伺服器B進入ESTABLISHED狀态,完成三次握手。

漫畫:一招學會TCP的三次握手和四次揮手

完成三次握手,用戶端與伺服器開始傳送資料。

TCP 四次揮手

TCP斷開連結的過程和建立連結的過程比較類似,隻不過中間的兩部并不總是會合成一步走,是以它分成了4個動作,Client揮手(fin)——Server傷感地微笑(ack)——Server揮手(fin)——Client傷感地微笑(ack)。

漫畫:一招學會TCP的三次握手和四次揮手

之是以中間的兩個動作沒有合并,是因為tcp存在「半關閉」狀态,也就是單向關閉。Client已經揮了手,可是人還沒有走,隻是不再說話,但是耳朵還是可以繼續聽,Server呢繼續喊話。等待Server累了,也不再說話了,超Client揮了揮手,Client傷感地微笑了一下,才徹底結束了。

漫畫:一招學會TCP的三次握手和四次揮手

上面有一個非常特殊的狀态time_wait,它是主動關閉的一方在回複完對方的揮手後進入的一個長期狀态,這個狀态标準的持續時間是4分鐘,4分鐘後才會進入到closed狀态,釋放套接字資源。不過在具體實作上這個時間是可以調整的。

它就好比主動分手方要承擔的責任,是你提出的要分手,你得付出代價。這個後果就是持續4分鐘的time_wait狀态,不能釋放套接字資源(端口),就好比守寡期,這段時間内套接字資源(端口)不得回收利用。

它的作用是重傳最後一個ack封包,確定對方可以收到。因為如果對方沒有收到ack的話,會重傳fin封包,處于time_wait狀态的套接字會立即向對方重發ack封包。

同時在這段時間内,該連結在對話期間于網際路由上産生的殘留封包(因為路徑過于崎岖,資料封包走的時間太長,重傳的封包都收到了,原始封包還在路上)傳過來時,都會被立即丢棄掉。4分鐘的時間足以使得這些殘留封包徹底消逝。不然當新的端口被重複利用時,這些殘留封包可能會幹擾新的連結。

4分鐘就是2個MSL,每個MSL是2分鐘。MSL就是maximium segment lifetime——最長封包壽命。這個時間是由官方RFC協定規定的。至于為什麼是2個MSL而不是1個MSL,我還沒有看到一個非常滿意的解釋。

四次揮手也并不總是四次揮手,中間的兩個動作有時候是可以合并一起進行的,這個時候就成了三次揮手,主動關閉方就會從fin_wait_1狀态直接進入到time_wait狀态,跳過了fin_wait_2狀态。

TCP四次分手總結

由于TCP連接配接是全雙工的,是以每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料發送任務後就能發送一個FIN來終止這個方向的連接配接。收到一個 FIN隻意味着這一方向上沒有資料流動,一個TCP連接配接在收到一個FIN後仍能發送資料。首先進行關閉的一方将執行主動關閉,而另一方執行被動關閉。

漫畫:一招學會TCP的三次握手和四次揮手
  1. 用戶端A發送一個FIN,用來關閉客戶A到伺服器B的資料傳送(封包段4)。
  2. 伺服器B收到這個FIN,它發回一個ACK,确認序号為收到的序号加1(封包段5)。和SYN一樣,一個FIN将占用一個序号。
  3. 伺服器B關閉與用戶端A的連接配接,發送一個FIN給用戶端A(封包段6)。
  4. 用戶端A發回ACK封包确認,并将确認序号設定為收到序号加1(封包段7)。

總結

TCP狀态轉換是一個非常複雜的過程,本文僅對一些簡單的基礎知識點進行了類比講解。關于TCP的更多知識還需要讀者去搜尋相關技術文章進入深入學習。如果讀者對TCP的基礎知識掌握得比較牢固,進階的知識了解起來就不會太過于吃力。

補充

最近作為面試管在面試的時候,發現很多人架構很強,java基礎的時候就有些薄弱了,很多童鞋們對于HTTP、TCP、UDP以及SOCKET的概念不是很清楚,傻傻的分不清楚,這裡我們也簡單的提一下

HTTP本身就是一個協定,是從Web伺服器傳輸超文本到本地浏覽器的傳送協定。

HTTP(超文本傳輸協定)是利用TCP在兩台電腦(通常是Web伺服器和用戶端)之間傳輸資訊的協定。用戶端使用Web浏覽器發起HTTP請求給Web伺服器,Web伺服器發送被請求的資訊給用戶端。

HTTP協定是建立在請求/響應模型上的。首先由客戶建立一條與伺服器的TCP連結,并發送一個請求到伺服器,請求中包含請求方法、URL、協定版本以及相關的MIME樣式的消息。伺服器響應一個狀态行,包含消息的協定版本、一個成功和失敗碼以及相關的MIME式樣的消息。

HTTP/1.0為每一次HTTP的請求/響應建立一條新的TCP連結,是以一個包含HTML内容和圖檔的頁面将需要建立多次的短期的TCP連結。一次TCP連結的建立将需要3次握手。

另外,為了獲得适當的傳輸速度,則需要TCP花費額外的回路連結時間(RTT)。每一次連結的建立需要這種經常性的開銷,而其并不帶有實際有用的資料,隻是保證連結的可靠性,是以HTTP/1.1提出了可持續連結的實作方法。HTTP/1.1将隻建立一次TCP的連結而重複地使用它傳輸一系列的請求/響應消息,

是以減少了連結建立的次數和經常性的連結開銷。

雖然HTTP本身是一個協定,但其最終還是基于TCP的。

SOCKET:TCP/IP網絡的API。

Socket是應用層與TCP/IP協定族通信的中間軟體抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協定族隐藏在Socket接口後面,對使用者來說,一組簡單的接口就是全部,讓Socket去組織資料,以符合指定的協定。

Socket 接口是TCP/IP網絡的API,Socket接口定義了許多函數或例程,用以開發TCP/IP網絡上的應用程式。

這是為了實作以上的通信過程而建立成來的通信管道,其真實的代表是用戶端和伺服器端的一個通信程序,雙方程序通過socket進行通信,而通信的規則采用指定的協定。socket隻是一種連接配接模式,不是協定,tcp,udp,簡單的說(雖然不準确)是兩個最基本的協定,很多其它協定都是基于這兩個協定如,http就是基于tcp的,用socket可以建立tcp連接配接,也可以建立udp連接配接**,這意味着,用socket可以建立任何協定的連接配接,因為其它協定都是基于此的。

漫畫:一招學會TCP的三次握手和四次揮手

綜上所述:需要IP協定來連接配接網絡;TCP是一種允許我們安全傳輸資料的機制,使用TCP協定來傳輸資料的HTTP是Web伺服器和用戶端使用的特殊協定。HTTP基于TCP協定,但是卻可以使用socket去建立一個TCP連接配接。