問題:TCP連接的三次握手

三次握手、四次揮手

先明確幾個關鍵字:

同步 SYN :synchronous。建立連接,將 SYN = 1。
序號 seq :sequence。第一個字節(jié)的編號隨機產(chǎn)生。
確認位 ACK: acknowledgement 。
ack :表示確認字段的值。
結束 FIN : finish。FIN = 1 表示希望斷開連接。
重置RST:重置。

三次握手

  • 第一次握手:客戶端發(fā)送同步信號 SYN 和一個隨機序列號 seq = x到服務器,并進入 SYN_SEND 狀態(tài),等待服務器確認;

  • 第二次握手:服務器收到 客戶端的同步信號,返回確認位 AKC = 1 ,并將傳來的 x 加上 1 的ack=x+1返回
    同時自己也發(fā)送一個 同步信號SYN 和一個隨機序列號 seq=y給客戶端,即 SYN+ACK 包,此時服務器進入 SYN_RECV 狀態(tài);

  • 第三次握手:客戶端確認收到 服務器 的同步信號SYN+ACK包,返回確認位 ACK = 1 ,并將傳來的 y 加上 1 的ack=y+1返回,此時更新后的 seq = x + 1 也一并返回,此包發(fā)送完畢,客戶端和服務器進入 ESTABLISHED 狀態(tài),完成三次握手。

握手過程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務器才正式開始傳送數(shù)據(jù)。理想狀態(tài)下,TCP 連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。斷開連接時服務器和客戶端均可以主動發(fā)起斷開 TCP 連接的請求,斷開過程需要經(jīng)過下面提到的“四次揮手”

三次握手.gif

為什么需要三次握手呢?為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產(chǎn)生錯誤。
  • 防止舊的重復連接初始化造成混亂,避免資源浪費。

謝希仁版《計算機網(wǎng)絡》中的例子是這樣的,“已失效的連接請求報文段” 的產(chǎn)生在這樣一種情況下:
client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是一個早已失效的報文段,但是server收到此失效的連接請求報文段后,就誤認為是client再次發(fā)出的一個新的連接請求,于是就向client發(fā)出確認報文段,同意建立連接。
假設不采用“三次握手”,那么只要server發(fā)出確認,新的連接就建立了,由于client并沒有發(fā)出建立連接的請求,因此不會理睬server的確認,也不會向server發(fā)送數(shù)據(jù),但server卻以為新的運輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。所以沒有采用“三次握手”,這種情況下server的很多資源就白白浪費掉了。
白話一點就是,如果只有兩次握手,那么:
1. A 向 B 發(fā)送了第一個請求,但是因為網(wǎng)絡堵塞沒有到達
2. 超時后,于是 A 又發(fā)送了第二個請求,這此正常到達,而且 B 回復收到了
3. A 這時就開始和 B 相互通信,并一段時間后結束了連接
4. 此時最開始的請求到達了 B,B 以為 A 又請求了連接,并且回復了 A
5. 但 A 認為自己并沒有發(fā)送請求,所以并不會理睬 B, B 就只能一直等著

  • 同步雙方的初始序列號

三次握手主要是為了初始化 Sequence Number,即上述中的 seq,seq的作用就是確保數(shù)據(jù)包的有序傳輸,數(shù)據(jù)也是通過 seq 進行數(shù)據(jù)的拼接
舉例:
1. 客戶端先發(fā)送了一個請求連接的數(shù)據(jù)包,初始 seq = 100 , 因為網(wǎng)絡阻塞收不到回復,于是又發(fā)送了一個請求連接的數(shù)據(jù)包,初始 seq = 200
2. 此時網(wǎng)絡又恢復了正常,服務端接收到了最開始發(fā)送的 seq = 100, 于是返回 ack = 101
3. 客戶端比較上下文,發(fā)現(xiàn)自己希望收到的 ack 應該是 201,于是發(fā)送了 RST 給服務端,中止連接。
4. 一段時間后 seq = 200 到達了服務端,并返回了 ack = 201 以及自己的 seq 客戶端確認信息,返回服務端的 seq + 1,建立TCP連接

第二次握手如果客戶端沒有收到服務端發(fā)送 SYN-ACK 報文怎么辦呢?

此時服務端會進行重試,Linux 默認是等待 63s 后斷開連接。
第一次等待 1 秒,第二次等待 2 秒,第三次等待 4 秒,第四次等待 8 秒,第五次等待 16 秒,再等待 32 秒后服務器會斷開連接。
總共等待時間為 1 + 2 + 4 + 8 + 16 + 32 = 63 秒。

第三次握手ACK 確認包丟失怎么辦

三次握手其實解決了第二步的數(shù)據(jù)包丟失問題。那么第三步的 ACK 確認丟失后,TCP 協(xié)議是如何處理的呢?

按照 TCP 協(xié)議處理丟包的一般方法,服務端會重新向客戶端發(fā)送數(shù)據(jù)包,直至收到 ACK 確認為止。但實際上這種做法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊,是指發(fā)送方偽造多個 IP 地址,模擬三次握手的過程。當服務器返回 ACK 后,攻擊方故意不確認,從而使得服務器不斷重發(fā) ACK。由于服務器長時間處于半連接狀態(tài),最后消耗過多的 CPU 和內(nèi)存資源導致死機。

正確處理方法是服務端發(fā)送 RST 報文,進入 CLOSE 狀態(tài)。這個 RST 數(shù)據(jù)包的 TCP 首部中,控制位中的 RST 位被設置為 1。這表示連接信息全部被初始化,原有的 TCP 通信不能繼續(xù)進行??蛻舳巳绻€想重新建立 TCP 連接,就必須重新開始第一次握手。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容