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

TCP三次握手和四次揮手的問題在面試中是最爲常見的考點之一。不少讀者都知道三次和四次,可是若是問深刻一點,他們每每都沒法做出準確回答。

本篇嘗試使用動畫來對這個知識點進行講解,指望讀者們能夠更加簡單地地理解TCP交互的本質。java

image

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

可分爲四個層次面試

  • 一、數據鏈路層、網絡層、傳輸層和應用層。
  • 二、 在網絡層:有IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議。
  • 三、在傳輸層:中有TCP協議與UDP協議。
  • 四、在應用層:有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%確認,因此要經過招手的方式相互肯定對方是否定識本身。安全

image

相互擁抱服務器

image

咱們看到這個過程當中一共是四個動做,招手–點頭微笑–招手–點頭微笑。其中連續進行了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 數據傳輸就是兩我的隔空對話,差了一點距離,因此須要對方反覆確認聽見了本身的話。併發

image

客戶端喊了一句話(data),接收方聽見了以後要回複本身聽見了(ack)。框架

若是喊了一句,半天沒聽到對方回覆,就認爲本身的話被大風吹走了,沒聽見,因此須要從新喊話,這就是tcp重傳。

也有多是服務端聽到了客戶端的話,可是Server向Client的回覆被大風吹走了,以致於Client沒聽見Server的回覆。Client並不能判斷到底是本身的話被大風吹走了仍是Server的回覆被大風吹走了,Client也不用管,重傳一下就是。

image

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狀態,完成三次握手。

image

完成三次握手,客戶端與服務器開始傳送數據。

TCP 四次揮手

TCP斷開連接的過程和創建連接的過程比較相似,只不過中間的兩部並不老是會合成一步走,因此它分紅了4個動做,Client揮手(fin)——Server傷感地微笑(ack)——Server揮手(fin)——Client傷感地微笑(ack)。

image

之因此中間的兩個動做沒有合併,是由於tcp存在「半關閉」狀態,也就是單向關閉。Client已經揮了手,但是人尚未走,只是再也不說話,可是耳朵仍是能夠繼續聽,Server呢繼續喊話。等待Server累了,也再也不說話了,超Client揮了揮手,Client傷感地微笑了一下,才完全結束了。

image

上面有一個很是特殊的狀態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後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。

image

  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能夠建立任何協議的鏈接,由於其它協議都是基於此的。

image

綜上所述:須要IP協議來鏈接網絡;TCP是一種容許咱們安全傳輸數據的機制,使用TCP協議來傳輸數據的HTTP是Web服務器和客戶端使用的特殊協議。HTTP基於TCP協議,可是卻可使用socket去創建一個TCP鏈接。

更多參考

Android插件包換膚(高仿網易雲音樂換膚)

Android中Application是單例,正確嗎?

Android App瘦身新姿式——Android App Bundle

關於Java中的不可變性

最後若是對技術比較感興趣,歡迎關注個人微信公衆號:終端研發部,id:codeGooger,一塊兒進階技術

相關文章
相關標籤/搜索