1. 程式人生 > >tcp/ip----三次握手及四次揮手

tcp/ip----三次握手及四次揮手

三次握手與四次揮手

1. 序列號seq
佔4個位元組,用來標記資料段的順序,TCP把連線中傳送的所有資料位元組都編上一個序號,第一個位元組的編號由本地隨機產生,給位元組編上序號後,就給每一個報文段指派一個序號,序列號seq就是這個報文段中的第一個位元組的資料編號。

2. 確認號ack
佔4個位元組,期待收到對方下一個報文段的第一個資料位元組的序號,序列號表示報文段攜帶資料的第一個位元組的編號,而確認號指的是期望接受到下一個位元組的編號,因此擋牆報文段最後一個位元組的編號+1即是確認號。

3. 確認ACK
佔1個位元位,僅當ACK=1,確認號欄位才有效。ACK=0,確認號無效。

4. 同步SYN
連線建立時用於同步序號。當SYN=1,ACK=0表示:這是一個連線請求報文段。若同意連線,則在響應報文段中使用SYN=1,ACK=1.因此,SYN=1表示這是一個連線請求,或連線接收報文,SYN這個標誌位只有在TCP建立連線才會被置為1,握手完成後SYN標誌位被置為0.

5. 終止FIN
用來釋放一個連線。

 

下圖為tcp/ip建立連線到斷開連線的流程圖

建立連線(三次握手)

第一次握手:客戶端會向伺服器發出連線請求,其中包括(syn=1,seq=x,ack=0),其含義為,syn=1表示請求建立連線,seq=x表示客戶端傳送一個x的序列號,加入伺服器接收到,請回應一個為x+1的確認號給我。

第二次握手:服務端收到客戶端傳送過來的連線請求,回覆給客戶端一個數據包,其中包括(syn=1,seq=y,ack=x+1),其含義為,我收到了你的請求,給你回覆了一個x+1的確認號,並給你傳送一個為y的序列號,如果服務端收到,請回復一個為y+1的確認號。

第三次握手:客戶端收到服務端的回覆,傳送一個數據包給服務端,其中包括(seq=x+1,ack=y+1),其含義為,我收到了你的回覆,並給你傳送一個y+1的確認號,現在連線正式建立。

 

中間是連線建立的狀態

1.客戶端向伺服器發出data請求

2.服務端向客戶端回覆一個確認號,表示已經收到客戶端的請求。

3.服務端向客戶端傳送相應的data。

4.客戶端向伺服器回覆一個確認號,表示已經收到服務端的data。

以此不斷迴圈。

 

斷開連線(四次揮手)

step1:第一次揮手
首先,客戶端傳送一個FIN,關閉客戶端到伺服器的資料傳送,然後等待伺服器的確認。其中終止標誌位FIN=1,表示斷開連線,序列號seq=u。

step2:第二次揮手
伺服器收到這個FIN,向客戶端回覆一個u+1的確認號,表示收到客戶端的斷開連線請求。

step3:第三次揮手
關閉伺服器到客戶端的連線,傳送一個FIN給客戶端,seq=n。

step4:第四次揮手

客戶端收到FIN後,回覆伺服器一個n+1的確認號,表示已經收到服務端的斷開連線資訊。

首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

 

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


總結:

第三次握手是為了防止:如果客戶端遲遲沒有收到伺服器返回確認報文,這時會放棄連線,重新啟動一條連線請求,但問題是:伺服器不知道客戶端沒有收到,所以他會收到兩個連線,浪費連線開銷。如果每次都是這樣,就會浪費多個連線開銷。

 

常見面試題二:

1.為什麼需要四次揮手?

在資料傳輸的過程中,資料的傳輸是雙向的。當一方認為自己沒有資料需要傳送給對方了,便發起了斷開連線的請求,並斷開了自己到對端的連線,但是此時並不代表對端已經沒有資料需要傳輸給自己了,此時對方會先回復一個確認號,表示已經收到請求,但是由於資料還在傳輸,對端需要先把資料傳輸完成再斷開連線。最後傳送一個fin過來表示對端到自己的連線已經關閉了,自己傳送一個確認號給對端表示收到,此時連線才完全斷開。

 

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

2.為什麼需要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應答包。在TIME_WAIT狀態時兩端的埠不能使用,要等到2MSL時間結束才可以繼續使用。當連線處於2MSL等待階段時任何遲到的報文段都將被丟棄。

3.為什麼是四次揮手,而不是三次或是五次、六次?
雙方關閉連線要經過雙方都同意。所以,首先是客服端給伺服器傳送FIN,要求關閉連線,伺服器收到後會傳送一個ACK進行確認。伺服器然後再發送一個FIN,客戶端傳送ACK確認,並進入TIME_WAIT狀態。等待2MSL後自動關閉。

 

總結:
(1)為了保證客戶端傳送的最後一個ACK報文段能夠到達伺服器。即最後一個確認報文可能丟失,伺服器會超時重傳,然後伺服器傳送FIN請求關閉連線,客戶端傳送ACK確認。一個來回是兩個報文生命週期。

如果沒有等待時間,傳送完確認報文段就立即釋放連線的話,伺服器就無法重傳,因此也就收不到確認,就無法按步驟進入CLOSE狀態,即必須收到確認才能close。
(2)防止已經失效的連線請求報文出現在連線中。經過2MSL,在這個連續持續的時間內,產生的所有報文段就可以都從網路消失。

 

原文:https://blog.csdn.net/ZWE7616175/article/details/80432486