你應該這么理解TCP的三次握手和四次揮手


前言:


 

  1. TCP協議是計算機的基礎,他本身是一個非常非常復雜的協議。
  2. 本文只是蜻蜓點水,將從網絡基礎以及TCP的相關概念介紹開始,之后再將三次握手,四次揮手這些內容來闡述。
  3. 最后介紹一些常見問題,並給出解答。

 網絡分層


在實際的網絡中,我們是四層網絡結構:

 

網絡傳輸層

網絡傳輸層負責最底層的底層鏈路連接。兩台主機之間進行互聯,基於網線的物理硬件上的協議。在這個側面,主機與主機之間只認得硬件mac編碼。並不認識IP。

網絡層

IP就是在網絡層出現的,就像網絡上,每個機器的地址。網絡層可以理解為快遞,它的職能就是根據地址(IP),把東西從一個地方運送到另一個地方

傳輸層

傳輸層相比於網絡層最大的不同就是引入了端口的概念。網絡層只管發送地址和目的地址。但是發送主機上有可能有多個程序和同一個接收主機進行傳輸數據,怎么區分這多個程序呢?就引入了端口的概念。(發送IP地址,發送端口,接收IP地址,接收端口)四元組標示了一個主機的程序到另一個主機程序的唯一標示。傳輸層的職能,就是維護這個四元組。

其實傳輸層還有一個職能是定義發送方和接收方基本處理包的行為。上面說到網絡層就相當於郵件運輸工,它只負責把一包東西從一個地方放到另外一個地方,但是,這包東西是否送達了,送達之后接收方又有什么行為。這些都可以在傳輸層進行定義。注意,這里說的是可以,你也可以在傳輸層布不管這些,只做簡單的基本封裝四元組,比如UDP

應用層

指定到主機端口了,接下來就是應用層干活了,可以傳文件,傳文本。應用層就是實際上對具體的程序之間的交互功能進行定義的層。

 

TCP協議


TCP(Transmission Control Protocol) 傳輸控制協議.TCP是主機對主機層的傳輸控制協議,提供可靠的連接服務,采用三次握手確認建立一個連接。

協議結構如下:

這里就不全部都講了,主介紹一部分:

 

Source Port和Destination Port

這兩個字段表示發送地址和目的地址的端口號,發送地址的IP和目的地址的IP是在IP協議頭中

 

Sequence number(順序號碼) Acknowledge number(確認號碼)

TCP的任意一端(不管是客戶端還是服務端),可以發送數據,也可以接受數據。那么發送序列號就是Seqence Number,接受序列號就是Acknowledgement Number。

其次,序列號是用來標志包的順序的。網絡中包由於網絡問題,接受到的並不是按順序到達的,接受端可以根據這個序列號來進行組裝。

比如:

給服務端發送8000字節的數據,順序號從10000開始,分成4個包發送,那么它們的標識就是12000,14000,16000,18000。

如下圖所示,由於網絡問題,最先到達的是序號為14000,但是服務端可以根據這些包的序號進行拼接,拼成完整的包。

 

 

Data offset和Reserved

由於tcp頭可能是不固定大小的(因為存在可選字段),所以需要有這個值來表示當前這個包的tcp頭有多大。

Reserved就是保留字段

 

位碼TCP標志位

就是下圖中的紅框的內容

 

SYN(synchronous建立聯機):建立連接,發送一方告知另外一方,請求建立連接

ACK(acknowledgement 確認):該包中有回復信息

PSH(push傳送):該包中有傳輸信息

FIN(finish結束):結束位,發送一方告知另外一方,請求中斷連接

RST(reset重置):重置位,這個包是用來要對方重置連接

URG(urgent緊急):緊急位,已經建議棄用

 

握手與揮手:


 有了上面的基礎知識,相信下面的三次揮手和四次握手理解起來也不會費勁的。

下圖是三次握手的過程:

 

 

 

三次握手過程說明:

TCP服務器進程先創建傳輸控制塊TCB(存儲了每一個連接中的一些重要信息,如:TCP連接表,到發送和接收緩存的指針,到重傳隊列的指針,當前的發送和接收序號,等),准備接受客戶進程的連接請求。然后服務器進程就處於LISTEN(收聽)狀態,等待客戶的連接請求。如有,即作出相應。

第一次握手:

客戶端Client向服務端Server發起建立連接請求。客戶端會發送位碼SYN(請求建立連接),以及序列號x(seq=x),TCP規定,SYN報文段(即SYN=1的報文段)不能攜帶數據,但要消耗掉一個序號。這時,TCP客戶進程進入SYN-SENT(同步已發送)狀態。

第二次握手:

服務端Server接受到請求報文段之后。如同意建立連接,則向客戶端發送確認消息。在確認報文段中應把SYN位和ACK位都置1,確認號是ack=x+1,同時也為自己選擇一個初始序號seq=y。注意。這個報文段也不能攜帶數據,但同樣要消耗掉一個序號。這時服務端進程進入SYN-RCVD(同步收到)狀態。

第三次握手:

客戶端Client收到服務端Server的確認后,還要向服務端給出確認。確認報文段的ACK置1,確認號ack=y+1,而自己的序號seq=x+1。這時,TCP連接已經建立,客戶端進入ESTABLISHED(已連接狀態)。當服務端收到客戶端的確認之后,也進入ESTABLISHED狀態。

 

總結:

客戶端在三次握手中,狀態的轉變是:CLOSED->SYN_SEND->ESTABLISHED

服務端在三次握手中,狀態的轉變是:CLOSED->LISTENED->SYN_RCVD->ESTABLISHED

 

問題一:為什么不可以兩次握手,為什么客戶端還要再發送一次確認?

答:消除舊有連接請求的SYN消息對新連接的干擾,同步連接雙方的序列號和確認號並交換TCP 窗口大小信息。

  比如說這種異常情況:客戶端發出的第一個連接請求報文段並沒有丟失,而是在某些網絡結點長時間滯留了,以致延誤到連接釋放以后的某個時間才到達服務端。本來這是一個早已失效的報文段。但服務端收到此失效的連接請求報文段后,就誤以為是客戶端又發出一次新的連接請求。於是就向客戶端發出確認報文段,同意建立連接。假定不采用三次握手,那么只要服務端發出確認,新的連接就建立了。

問題二:什么是SYN攻擊?如何檢測它?

   在三次握手過程中,服務器發送SYN-ACK之后,收到客戶端的ACK之前的TCP連接稱為半連接(half-open connect).此時服務器處於Syn_RECV狀態.當收到ACK后,服務器轉入ESTABLISHED狀態.

  Syn攻擊就是 攻擊客戶端 在短時間內偽造大量不存在的IP地址,向服務器不斷地發送syn包,服務器回復確認包,並等待客戶的確認,由於源地址是不存在的,服務器需要不斷的重發直 至超時,這些偽造的SYN包將長時間占用未連接隊列,正常的SYN請求被丟棄,目標系統運行緩慢,嚴重者引起網絡堵塞甚至系統癱瘓。

  Syn攻擊是一個典型的DDOS攻擊。檢測SYN攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊.在Linux下可以如下命令檢測是否被Syn攻擊:

netstat -n -p TCP | grep SYN_RECV

一般較新的TCP/IP協議棧都對這一過程進行修正來防范Syn攻擊,修改tcp協議實現。主要方法有SynAttackProtect保護機制、SYN cookies技術、增加最大半連接和縮短超時時間等.

但是不能完全防范syn攻擊。

 

四次揮手過程說明:

 在客戶端和服務端已經建立連接的情況下,需要四次揮手來斷開連接。如下圖所示:

 

 

第一次揮手:

客戶端發送一個FIN=1的報文段和順序號為u(seq=u)的請求關閉消息(客戶端沒有消息要發給你了,我准備關閉連接了,但是如果你還有數據沒有發送完成,則不必急着關閉Socket,可以繼續發送數據。所以你先發送ACK)。客戶端進入FIN-WAIT-1狀態,等待服務端的FIN報文段。

第二次揮手:

服務端收到客戶端的FIN報文段,會發送一個確認報文段ACK=1,以及確認序列號ack=u+1,還有自己的序列號seq=v(告訴客戶端,我已經收到你的請求關閉消息,但是我還沒准備好,請繼續等待),服務單進入CLOSE-WAIT階段,此時服務端還未關閉。

第三次揮手:

服務端向客戶端發送FIN=1報文段(告訴Client端,好了,我這邊數據發完了,准備好關閉連接了),ACK=1,序列號seq=w,ack=u+1,服務端進入LAST-ACK狀態

第四次揮手:

客戶端收到服務端發來的FIN=1報文段,給服務端發送ACK=1報文段,序列號seq=u+1,ack=w+1的消息。這時客戶端就可以關閉連接了,但是他還是不相信網絡,怕Server端不知道要關閉,所以發送ACK后進入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳 ,客戶端等待了2MSL后依然沒有收到回復,客戶端關閉。服務端也關閉。

 

總結:

客戶端在四次揮手中的狀態變化是:ESTABLISHED -> FIN-WAITED-1 -> FIN-WAITED-2 -> TIME-WAITED -> CLOSED

服務單在四次揮手中的狀態變化是:ESTABLISHED -> CLOSE-WAITED LAST-ACK -> CLOSED

 

問題一:為什么在第四次回收后會有2個MSL的延時?

首先了解MSL,Maximum Segment Lifetime,最大報文生存時間,2個MSL是報文段發送和接受的最長時間。

假定網絡不可靠,那么第四次發送的ACK可能丟失,即服務端無法收到這個ACK,如果服務端收不到這個確認ACK,服務端會定時向客戶端端重復發送FIN,直到服務單端收到客戶端的確認ACK。所以這個2MSL就是用來處理這個可能丟失的ACK的。

問題二:為什么握手只要三次,揮手卻需要四次?

在TCP連接中,服務端SYN和ACK向客戶端發送是一次性發送的,而在斷開連接的過程中,服務端向客戶端發送的ACK和FIN是分兩次發送的。因為在服務端接受到客戶端的FIN后,服務端還有數據要傳輸的話,所以先發送ACK,等服務端處理完自己的事情后就可以發送FIN斷開連接了。

 

下篇預告:

TCP長連接與短連接,與Socket的聯系

 

參考鏈接:

漫談TCP

TCP的三次握手和四次揮手

TCP協議三次握手過程分析

計算機網絡——TCP三次、四次握手詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM