{{ v.name }}
{{ v.cls }}類
{{ v.price }} ¥{{ v.price }}
圖片
在了解三次握手四次揮手前必須先了解什么是tcp。
TCP是面向連接的,可靠的,基于字節流的傳輸層協議。
所謂連接其實是保證可靠性和流量控制的狀態信息的總和,包括sokict,滑動窗口和序列號。
tcp通過序列號,重傳機制,滑動窗口等一系列控制機制保證數據的無重復,無丟失,有序的被接受端處理。
tcp的數據是基于字節流,因此是無邊界,數據是可以無限大的,tcp可以通過分片機制將數據有序發送到接收端。
TCP的頭部在無“選項”字段的情況下是20個字節。包括:
這里需要說明的是“選項”這個字段是用來輔助解決可靠性問題的,正是因為這個字段的長度是不確定的,所以需要“首部長度”這個字段來表示TCP頭部的長度。
圖片
TCP是基于連接的,所以TCP在使用前必須先建立連接,TCP建立連接的過程是基于三次握手的。
至此,tcp連接建立完成,注意第三次握手是可以傳輸數據的。在這之前不能傳輸數據。
一般大家都會認為三次握手是為了保證客戶端和服務端雙方都能確認自身和接收端建立單向連接和保證自身能夠發送和接受成功數據。
這樣答本身也沒有錯,但是太粗化了。
既然握手是為保證連接的建立,那就要先知道什么是TCP連接。
TCP連接是保證可靠性和流量控制的狀態信息的總和,包括socket,序列號,滑動窗口。
在這里這個序列號至關重要,是保證消息無重復,無丟失,有序的關鍵,因此這里其實就是為了保證序列號的同步。
客戶端給服務端發送一個初始序列號,服務端回復syn+ack,就是告訴客戶端序列號已經收到了并且把服務端的初始序列號發送給客戶端,客戶端收到后也要回復給服務端表示序列號已經收到,這樣就能保證雙方都能確保序列號同步。
但是這還不是最重要的原因,最重要的原因是防止歷史連接初始化再次連接。比如有這樣一種情況,客戶端發送syn包給服務端,但是網絡阻塞了,服務端沒有收到,所以服務端也不會回復,客戶端收不到回復就會重新發送syn包,但是就在這時候服務端接收到了第一個syn包,并且回復客戶端,這個時候客戶端會進行比對校驗這是不是自己最新發送的syn回復包,如果不是的話就會給服務端發送rst包,表示要求服務端中斷這個連接。這也是三次握手的意義所在。
如果說沒有第三次握手,那么在發生上面的這個情況后,服務端就會為每個syn請求創建連接,連接是需要占用內存的,就會耗費很多的資源。造成資源浪費,所以三次握手很有必要。
那么四次握手是否可以呢?
四次握手的話也是可以的,四次握手其實就是客戶端發送syn包給服務端,服務端回復ack包,服務端發送syn包給客戶端,客戶端回復ack包,三次握手中的第二次握手回復的是syn+ack包,所有相當于合并了四次握手中的中間兩次,所以三次握手最好。
圖片
TCP是雙向連接,所以兩個方向上的連接都要斷開。
在網絡傳輸的世界里,有兩個值是用來表示數據包失效的:
所以一般情況下MSL會大于TTL減為0所消耗的時間。
因為當客戶端接收到服務端的fin包后,會向服務端回復ack,但是客戶端不知道這個ack是否發送成功了,所以客戶端需要確認服務端接受成功后才能置為close狀態,怎么確認呢,因為失敗重傳機制的存在,如果因為網絡阻塞服務端沒有收到ack,服務端會再次發送一次fin,一次ack包和再一次fin包就是2倍的MSL。MSL的計時是從收到fin包并且發送ack包開始的。
除了上面說的保證客戶端的ack發送到服務端,并被正確接收,從而保證被關閉連接的一方可以正確關閉。
還能保證那些阻塞在網絡中舊的連接,在端口又被復用的情況下,被接收到,這樣就會發生數據錯亂,而time_wait可以保證全部的網絡中的連接被丟棄。
MSL默認是30秒。需要注意的是time_wait 的狀態多了以后會占用內存資源和端口資源,所以不宜太多。
tcp是雙向連接,客戶端發送fin包給服務端,服務端回復ack,只是客戶端告訴服務端不再向服務端發送數據。
還需要服務端告訴客戶端,服務端不再向客戶端發送數據了,也就是服務端也要想客戶端發送fin包,客戶端也要給服務端回復ack包,這時候服務端和客戶端才能進入close狀態。
服務端在收到客戶端發送的fin包并回復ack包后,服務端并不能馬上向發送端發送fin包,因為此時可能還有連接在處理數據,必須等到數據處理完后才能向客戶端發送fin包。
正因為這個原因,不能像三次握手那樣把中間兩次合并。