Alamofire前奏之TCP三握四揮

創建TCP須要三次握手才能創建,而斷開鏈接則須要四次揮手。服務器

1、TCP三次握手🤝

TCP有6種標識:SYN(創建聯機)、ACK(確認)、PSH(傳送)、FIN(結束)、RST(重置)、URG(緊急)網絡

上圖所示即爲TCP三次握手的請求示意圖。

一、第1次握手

客戶端向服務端發送鏈接請求報文。這時,報文首部中的同步序號SYN=1,同時隨機生成初始序列號seq=x。此時,TCP客戶端進程進入了SYN_SENT(同步已發送狀態)狀態。3d

TCP規定,SYN報文段(SYN=1的報文段)不能攜帶數據,但須要消耗掉一個序號。這是三次握手中的開始,表示客戶端想和服務端創建鏈接。cdn

二、第2次握手

服務端收到請求報文後,若是贊成創建鏈接,則發出確認報文。確認報文中SYN=1ACK=1,確認序號ack=x+1,同時也爲服務端隨機初始化一個序列號seq=y。此時,服務端進程進入了SYN_RCVD(同步收到)狀態。blog

這個報文也不攜帶數據,而且也要消耗掉一個序號。這個報文帶有SYN(創建鏈接)和ACK(確認)標識。表示服務端詢問客戶端是否準備好鏈接。進程

三、第3次握手

客戶端收到服務器發送的確認後,還要給服務端發送確認報文。確認報文中ACK=1ack=y+1。此時,TCP鏈接創建,客戶端進入ESTABLISHED(已創建鏈接)狀態。資源

至此,客服端與服務端鏈接創建成功,能夠互相通訊了。同步

2、TCP數據的傳輸過程

在創建鏈接後,兩臺主機就能夠相互傳輸數據了。如圖所示: it

一、主機A初始 seq爲1200滑動窗體爲100,向主機B傳遞數據。

二、假設主機B在徹底成功接收數據的基礎上,主機B爲了確認這數據是否接收徹底,向主機A發送ACK包,並將Ack號設置爲1301。io

確認Ack號公式:Ack號 = Seq號 + 傳遞的字節數 + 1

三、主機A得到B傳來的Ack(1301)後,開始發送Seq爲1301,滑動窗體爲100的數據。

如此循環。。。直到數據所有發送完成。但這只是數據徹底發送正確的狀況,假如某個數據包由於某種緣由丟失了,那又該如何呢?以下圖所示

上圖所示中,經過 Seq=1301數據包向主機B傳遞100字節的數據,但中間發生了錯誤,致使主機B未收到。通過一段時間後,主機A仍未收到對於Seq 1301 的ACK確認,所以嘗試數據重傳。

爲了完成數據重傳,TCP套接字每次發送數據包時都會啓動定時器,若是在必定時間內沒有收到目標機器傳回的ACK確認包,那麼當定時器超時時,數據包就會被重傳。

3、TCP四次揮手👋

上圖所示即爲TCP四次揮手示意圖。

一、第1次揮手

客戶端發送一個FIN(結束),用來關閉客戶端與服務端之間的鏈接。

客戶端進程發出鏈接釋放報文,而且中止發送數據。釋放數據報文首部中FIN=1,其序列號seq=u(等於前面已經傳送過來的數據的最後一個字節的序號加1)。此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。

二、第2次揮手

服務端收到這個FIN,服務端發回一個ACK(確認)報文,ACK=1ack=u+1,而且帶上本身的序列號seq=v。此時,服務端進入CLOSE-WAIT(關閉等待)狀態。

服務端通知高層的應用進程,客戶端向服務端的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據發送了,可是服務器若發送數據,客戶端依然要接收。這個狀態還要持續一段時間,這段時間就是CLOSE-WAIT狀態持續的時間。

客戶端收到服務器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送鏈接釋放報文。

三、第3次揮手

服務端發送一個FIN(結束)到客戶端,服務端關閉客戶端的鏈接。

服務器將最後的數據發送完畢後,就向客戶端發送鏈接釋放報文,FIN=1ack=w+1。因爲在半關閉狀態,服務器極可能又發送數據,假定此時的序列號爲seq=w。此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。

四、第4次揮手

客戶端發送ACK(確認)報文確認,並將確認的序號+1,關閉鏈接完成。

客戶端收到服務器的鏈接釋放報文後,必須發出確認,ACK=1ack=w+1,本身的序列號seq=u+1。此時,客戶端就進入了TIME-WAIT(時間等待)狀態。

注意:此時TCP鏈接尚未釋放,必須通過2MSL(最後報文段壽命)的時間後,沒有收到服務器端的ACK,認爲服務器端已經正常關閉鏈接,因而本身也關閉鏈接,進入CLOSED狀態。

服務端在收到ACK確認報文後,就當即進入CLOSED狀態。

4、關於三握四揮的思考

一、爲何要三次握手?而不是兩次握手?

假如客戶端發送了第一個鏈接的請求報文,可是因爲網絡很差,這個請求沒有當即到達服務端,而是在某個網絡節點中滯留了,直到某個時間纔到達服務端。

原本這已是一個失效的報文,可是服務端接收到這個請求報文後,仍是會向客戶端發出確認的報文,表示贊成鏈接。

假如不採用三次握手,那麼只要服務端發出確認,新的鏈接就創建了,但其實這個請求失效的,客戶端並不會再向服務端發送確認信息。可是服務端認爲鏈接已經創建,會一直等待客戶端發送數據。這樣,服務端的不少資源就白白浪費了,採用三次握手就是爲了防止這種狀況的發生。服務端會由於收不到客戶端的確認報文,就知道客戶端並無創建鏈接。

爲了保證有效鏈接的創建,這就是三次握手的做用。

二、爲何要四次揮手?

當關閉鏈接時,當收到客戶端的FIN報文時,僅表示對方沒有數據發送了,可是並不表明服務端自身的全部數據都傳輸完成了,因此不必定會立刻關閉鏈接。只有當服務端的數據發送完畢後,服務端再次發送FIN報文給客戶端,來通知客戶端贊成關閉鏈接。

因此服務端在收到客戶端的FIN報文後,會發送一個ACK報文,表示確認收到關閉鏈接報文了,直到服務端報文數據傳輸完畢後,再發送FIN報文給客戶端表示服務端贊成關閉了。所以會有四次揮手。

相關文章
相關標籤/搜索