<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:TCP 為什么要三次握手與四次分手?大部分人答不上來!

          共 5747字,需瀏覽 12分鐘

           ·

          2022-02-21 19:12

          點擊關注公眾號,Java干貨及時送達

          作者:等不到的口琴
          來源:cnblogs.com/Courage129/p/14324605.html

          TCP協(xié)議簡介

          TCP協(xié)議是五層協(xié)議中運輸層的協(xié)議,下面依賴網(wǎng)絡層、鏈路層、物理層,對于一個報文想發(fā)到另一臺機器(假設是服務器)上對等層,每一個所依賴的層都會對報文進行包裝,例如TCP協(xié)議就依賴網(wǎng)絡層的IP協(xié)議,所以發(fā)送的報文會經(jīng)過如下封裝:

          TCP協(xié)議

          當這個數(shù)據(jù)包到達服務器時,服務器的網(wǎng)絡層會對IP相關協(xié)議內(nèi)容解封裝、校驗,然后運輸層對TCP層進行解封,解封涉及到一系列的步驟,例如這個數(shù)據(jù)包是要干嘛?是發(fā)給我的嗎?這些操作需要根據(jù) TCP 報文的首部信息來判斷,首部包含以下內(nèi)容:

          TCP 報文的首部信

          主要通過首部信息來了解這個包是干嘛的,關于首部信息,這兒需要用到的幾個如下:

          • ACK:TCP協(xié)議規(guī)定,只有ACK=1時有效,也規(guī)定連接建立后所有發(fā)送的報文的ACK必須為1
          • SYN(SYNchronization):在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文。對方若同意建立連接,則應在響應報文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個連接請求或連接接受報文。
          • FIN (finis):即完,終結的意思, 用來釋放一個連接。當 FIN = 1 時,表明此報文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接。

          「注意」·URG、ACK、PSH、PST、RST、SYN、FIN只有一位,也就是只有 0 或者 1 兩種狀態(tài)。

          TCP協(xié)議三次握手

          TCP協(xié)議三次握手

          「第一次握手」 :客戶端先向服務端發(fā)送一個請求連接的報文段,這個報文段SYN位設置為1,序列號Seq(Sequence Number)設置為某一值,假設為X,發(fā)送出去之后客戶端進入SYN_SEND狀態(tài),等待服務器的確認;

          「第二次握手」 :服務器收到SYN報文段。服務器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發(fā)送SYN請求信息,將SYN位置為1,Sequence Number為y;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一并發(fā)送給客戶端,此時服務器進入SYN_RECV狀態(tài);

          「第三次握手」 :客戶端收到服務器的SYN+ACK報文段。然后將Acknowledgment Number設置為y+1,向服務器發(fā)送ACK報文段,這個報文段發(fā)送完畢以后,客戶端和服務器端都進入ESTABLISHED狀態(tài),完成TCP三次握手。

          完成了三次握手,客戶端和服務器端就可以開始傳送數(shù)據(jù)。以上就是TCP三次握手的總體介紹。

          為什么要三次握手而不是兩次?

          為什么非要進行三次連接呢?兩次行嗎?類似的面試題整理好了,微信搜索Java技術棧,在后臺發(fā)送:面試,可以在線刷題。

          在謝希仁的《計算機網(wǎng)絡》中是這樣說的:

          為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產(chǎn)生錯誤。如下:

          “已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認為是client再次發(fā)出的一個新的連接請求。于是就向client發(fā)出確認報文段,同意建立連接。


          假設不采用“三次握手”,那么只要server發(fā)出確認,新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求,因此不會理睬server的確認,也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。這樣,server的很多資源就白白浪費掉了。


          采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況,client不會向server的確認發(fā)出確認。server由于收不到確認,就知道client并沒有要求建立連接?!?,防止了服務器端的一直等待而浪費資源。

          第三次握手失敗了怎么辦?

          在tcp三次握手中 第二次握手完成后connect 就成功返回了 如果第三次握手的ack包丟了 此時 客戶端已認為連接是成功的,如果沒有應用層的心跳包,客戶端會一直維護這個連接 請問如何避免這種情況?

          第二次握手服務器收到SYN包,然后發(fā)出SYN+ACK數(shù)據(jù)包確認收到并且請求建立連接,服務器進入SYN_RECV狀態(tài)。而這個時候第三次握手時客戶端發(fā)送ACK給服務器失敗了,服務器沒辦法進入ESTABLISH狀態(tài),這個時候肯定不能傳輸數(shù)據(jù)的,不論客戶端主動發(fā)送數(shù)據(jù)與否,服務器都會有定時器發(fā)送第二步SYN+ACK數(shù)據(jù)包,如果客戶端再次發(fā)送ACK成功,建立連接。

          如果一直不成功,服務器肯定會有超時(大概64s)設置,超時之后會給客戶端發(fā)「RTS報文」?(連接重置),進入CLOSED狀態(tài),防止SYN洪泛攻擊,這個時候客戶端應該也會關閉連接。點擊關注公眾號,Java干貨及時送達

          「SYN洪泛攻擊:」

          SYN攻擊利用的是TCP的三次握手機制,攻擊端利用偽造的IP地址向被攻擊端發(fā)出請求,而被攻擊端發(fā)出的響應 報文將永遠發(fā)送不到目的地,那么「被攻擊端在等待關閉這個連接的過程中消耗了資源」?,如果有成千上萬的這種連接,主機資源將被耗盡,從而達到攻擊的目的。

          TCP協(xié)議四次分手

          還是這個圖鎮(zhèn)帖:

          TCP協(xié)議四次分手

          四次分手,意思是某一端(可以使客戶端,也可以是服務器端)想結束會話斷開連接,那么具體流程是:

          「第一次分手」 :主機1,設置序列號Seq(Sequence Number)確認包ACK(Acknowledgment Number),假設seq為x+2,ACK=y+1,再將FIN標志位設置為1,向主機2發(fā)送FIN報文段;之后主機1進入FIN_WAIT_1狀態(tài);這表示主機1沒有數(shù)據(jù)要發(fā)送給主機2了;

          「第二次分手」 :主機2收到了主機1發(fā)送的FIN報文段,向主機1回一個ACK報文段(其值為接收到的FIN報文的seq值+1);主機1進入FIN_WAIT_2狀態(tài),等待主機二的斷開請求包FIN;

          「第三次分手」 :主機2向主機1發(fā)送FIN報文段,意思是我可以斷開連接了,請求關閉連接,同時主機2進入CLOSE_WAIT狀態(tài);

          「第四次分手」 :主機1收到主機2發(fā)送的FIN報文段,向主機2發(fā)送ACK報文段,值為剛剛接收到的FIN包Seq值+1,然后主機1進入TIME_WAIT狀態(tài);主機2收到主機1的ACK報文段以后,就關閉連接;此時,主機1等待2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

          為什么要四次揮手

          TCP是全雙工模式,這就意味著,當主機1發(fā)出FIN報文段時,只是表示主機1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,主機1告訴主機2,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了;但是,這個時候主機1還是可以接受來自主機2的數(shù)據(jù);當主機2返回ACK報文段時,表示它已經(jīng)知道主機1沒有數(shù)據(jù)發(fā)送了,但是主機2還是可以發(fā)送數(shù)據(jù)到主機1的;當主機2也發(fā)送了FIN報文段時,這個時候就表示主機2也沒有數(shù)據(jù)要發(fā)送了,就會告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了,之后彼此就會愉快的中斷這次TCP連接。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態(tài)變化。

          四次揮手狀態(tài)解釋

          FIN_WAIT_1 : 這個狀態(tài)要好好解釋一下,其實FIN_WAIT_1FIN_WAIT_2狀態(tài)的真正含義都是表示等待對方的FIN報文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時,它想主動關閉連接,向對方發(fā)送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態(tài)。「也就是,發(fā)出FIN包之后進入FIN_WAIT_1狀態(tài)」

          而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態(tài),當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時常常可以用netstat看到。「也就是,發(fā)出ACK報文之后進入FIN_WAIT_2狀態(tài)」最新面試題整理好了,大家可以在Java面試庫小程序在線刷題。

          「主動方FIN_WAIT_2 :上面已經(jīng)詳細解釋了這種狀態(tài),實際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數(shù)據(jù)需要傳送給你(ACK信息),稍后再關閉連接。

          「主動方CLOSE_WAIT :這種狀態(tài)的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發(fā)送FIN報文給自己,你系統(tǒng)毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態(tài)。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話,那么你也就可以 close這個SOCKET,發(fā)送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關閉連接。

          「被動方LAST_ACK : 這個狀態(tài)還是比較容易好理解的,它是被動關閉一方在發(fā)送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態(tài)了。「也就是接收到了對方的FIN包,自己發(fā)出了ACK以及FIN包之后的狀態(tài)」

          「被動方TIME_WAIT : 表示收到了對方的FIN報文,并發(fā)送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT1狀態(tài)下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)。想成為架構師,這份架構師圖譜建議看看,少走彎路

          「主動方CLOSED : 表示連接中斷。

          TCP狀態(tài)圖

          TCP狀態(tài)圖

          狀態(tài)圖解釋

          1. CLOSED:起始點,在超時或者連接關閉時候進入此狀態(tài)。
          2. LISTEN:svr端在等待連接過來時候的狀態(tài),svr端為此要調(diào)用socket, bind,listen函數(shù),就能進入此狀態(tài)。此稱為應用程序被動打開(等待客戶端來連接)。
          3. SYN_SENT:客戶端發(fā)起連接,發(fā)送SYN給服務器端。如果服務器端不能連接,則直接進入CLOSED狀態(tài)。
          4. SYN_RCVD:跟3對應,服務器端接受客戶端的SYN請求,服務器端由LISTEN狀態(tài)進入SYN_RCVD狀態(tài)。同時服務器端要回應一個ACK,同時發(fā)送一個SYN給客戶端;另外一種情況,客戶端在發(fā)起SYN的同時接收到服務器端得SYN請求,客戶端就會由SYN_SENT到SYN_RCVD狀態(tài)。
          5. ESTABLISHED:服務器端和客戶端在完成3次握手進入狀態(tài),說明已經(jīng)可以開始傳輸數(shù)據(jù)了。以上是建立連接時服務器端和客戶端產(chǎn)生的狀態(tài)轉移說明。相對來說比較簡單明了,如果你對三次握手比較熟悉,建立連接時的狀態(tài)轉移還是很容易理解。接下來服務器端和客戶端就進行數(shù)據(jù)傳輸。。。。,當然,里面也大有學問,就此打住,稍后再表。下面,我們來看看連接關閉時候的狀態(tài)轉移說明,關閉需要進行4次雙方的交互,還包括要處理一些善后工作(TIME_WAIT狀態(tài)),注意,這里主動關閉的一方或被動關閉的一方不是指特指服務器端或者客戶端,是相對于誰先發(fā)起關閉請求來說的。
          6. FIN_WAIT_1:主動關閉的一方,由狀態(tài)5進入此狀態(tài)。具體的動作時發(fā)送FIN給對方。
          7. FIN_WAIT_2:主動關閉的一方,接收到對方的FIN ACK,進入此狀態(tài)。由此不能再接收對方的數(shù)據(jù)。但是能夠向對方發(fā)送數(shù)據(jù)。
          8. CLOSE_WAIT:接收到FIN以后,被動關閉的一方進入此狀態(tài)。具體動作時接收到FIN,同時發(fā)送ACK。
          9. LAST_ACK:被動關閉的一方,發(fā)起關閉請求,由狀態(tài)8進入此狀態(tài)。具體動作時發(fā)送FIN給對方,同時在接收到ACK時進入CLOSED狀態(tài)。
          10. CLOSING:兩邊同時發(fā)起關閉請求時,會由FIN_WAIT_1進入此狀態(tài)。具體動作是,接收到FIN請求,同 時響應一個ACK。
          11. TIME_WAIT:最糾結的狀態(tài)來了。從狀態(tài)圖上可以看出,有3個狀態(tài)可以轉化成它,我們一一來分析:
          a.由FIN_WAIT_2進入此狀態(tài):在雙方不同時發(fā)起FIN的情況下,
          ????主動關閉的一方在完成自身發(fā)起的關閉請求后,接收到被動關閉一方的FIN后進入的狀態(tài)。
          b.由CLOSING狀態(tài)進入:雙方同時發(fā)起關閉,都做了發(fā)起FIN的請求,
          ????同時接收到了FIN并做了ACK的情況下,由CLOSING狀態(tài)進入。
          c.由FIN_WAIT_1狀態(tài)進入:同時接受到FIN(對方發(fā)起),ACK(本身發(fā)起的FIN回應),
          ????與b的區(qū)別在于本身發(fā)起的FIN回應的ACK先于對方的FIN請求到達,
          ????而b是FIN先到達。這種情況概率最小。

          關閉的4次連接最難理解的狀態(tài)TIME_WAIT,存在TIME_WAIT的 2 個理由:

          1. 可靠地實現(xiàn)TCP全雙工連接的終止。
          2. 允許老的重復分節(jié)在網(wǎng)絡中消逝。









          開工大吉!再發(fā) 10,000 個紅包封面
          2021 年發(fā)生的 10 件技術大事!!
          23 種設計模式實戰(zhàn)(很全)
          換掉 Log4j2!tinylog 橫空出世
          再見單身狗!Java 創(chuàng)建對象的 6 種方式
          勁爆!Java 協(xié)程要來了!
          重磅官宣:Redis 對象映射框架來了!!
          推薦一款代碼神器,代碼量至少省一半!
          程序員精通各種技術體系,45歲求職難!
          Spring Boot 3.0 M1 發(fā)布,正式棄用 Java 8
          Spring Boot 學習筆記,這個太全了!



          關注Java技術??锤喔韶?/strong>



          獲取 Spring Boot 實戰(zhàn)筆記!
          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国十大黄色操逼网站 | 天天干天天干天天日 | 高颜值呻吟给力 | 日P视频网站 | 欧美成人a v |