1. 程式人生 > >TCP的三次握手,四次揮手(不看後悔,一看必懂)

TCP的三次握手,四次揮手(不看後悔,一看必懂)

三次握手

step1:第一次握手

客戶端傳送資料包到伺服器,(在此連線請求報文段中的同步位SYN=1,確認ACK=0,表示這是一個TCP連線請求資料報文,序號seq=x,表示傳輸資料時的起始序號是x)此時,客戶端進入SYN_SENT狀態,等待伺服器確認

step2:第二次握手

伺服器收到連線請求報文段後,若同意建立連線,則向客戶端傳送確認報文段。此時伺服器進入SYN_RECV狀態。(其中確認報文段中,標識位SYN=1,ACK=1,表示這是一個TCP連線響應資料報文,並含服務端的初始序號seq(伺服器)=y,以及伺服器對客戶端初始序號的確認號ack(伺服器)=seq(客戶端)+1=x+1)。

step3:第三次握手

客戶端再次向伺服器傳送一個序列號(seq=x+1),確認號為ack(客戶端)=y+1,此包傳送完畢,客戶端和伺服器進入ESTAB_LISHED(TCP連線成功)狀態,完成三次握手。

常見面試題:

1.為什麼需要三次握手,兩次不可以嗎?或者四次、五次可以嗎? 
我們來分析一種特殊情況,如果是兩次握手,假設伺服器給客戶端在第二次握手時傳送資料,資料從伺服器發出,伺服器認為連線已經建立,但在傳送資料的過程中資料丟失,客戶端認為連線沒有建立,會進行重傳。假設每次傳送的資料一直在丟失,客戶端會一直向伺服器傳送請求連線,伺服器就會產生多個無效連線,佔用資源,這個時候伺服器可能會掛掉。這個現象就是我們聽過的“SYN的洪水攻擊”。

四次揮手

四次揮手過程(關閉客戶端到伺服器的連線)

step1:第一次揮手

首先,客戶端傳送一個FIN,用來關閉客戶端到伺服器的資料傳送,然後等待伺服器的確認。其中終止標誌位FIN=1,序列號seq=u。

step2:第二次揮手

伺服器收到這個FIN,它傳送一個ACK,確認ack為收到的序號加一。

step3:第三次揮手

關閉伺服器到客戶端的連線,傳送一個FIN給客戶端。

step4:第四次揮手

客戶端收到FIN後,併發回一個ACK報文確認,並將確認序號seq設定為收到序號加一。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

客戶端傳送FIN後,進入終止等待狀態,伺服器收到客戶端連線釋放報文段後,就立即給客戶端傳送確認,伺服器就進入CLOSE_WAIT狀態,此時TCP伺服器程序就通知高層應用程序,因而從客戶端到伺服器的連線就釋放了。此時是“半關閉狀態”,即客戶端不可以傳送給伺服器,伺服器可以傳送給客戶端。
此時,如果伺服器沒有資料報傳送給客戶端,其應用程式就通知TCP釋放連線,然後傳送給客戶端連線釋放資料報,並等待確認。客戶端傳送確認後,進入TIME_WAIT狀態,但是此時TCP連線還沒有釋放,然後經過等待計時器設定的2MSL後,才進入到CLOSE狀態。

為什麼客戶端在TIME-WAIT狀態需要等待2MSL時間?

 

首先,MSL即Maximum Segment Lifetime,就是最長報文段壽命,是任何報文在網路上的存在的最長時間,超過這個時間報文將被丟棄。《TCP/IP詳解》中是這樣描述的:MSL是任何報文段被丟棄前在網路內的最長時間。RFC 793中規定MSL為2分鐘,實際應用中常用的是30秒、1分鐘、2分鐘等。

TCP的TIME_WAIT需要等待2MSL,當TCP的一端發起主動關閉,三次揮手完成後傳送第四次揮手的ACK包後就進入這個狀態,等待2MSL時間主要目的是:防止客戶端傳送給伺服器的最後一個ACK包對方沒有收到,那麼對方在超時後將重發第三次握手的FIN包,主動關閉端接到重發的FIN包後可以再發一個ACK應答包。

為什麼是四次揮手,而不是三次或是五次、六次?

雙方關閉連線要經過雙方都同意。所以,首先是客服端給伺服器傳送FIN,要求關閉連線,伺服器收到後會傳送一個ACK進行確認。伺服器然後再發送一個FIN,客戶端傳送ACK確認,並進入TIME_WAIT狀態。等待2MSL後自動關閉。