TCP連線的建立(三次握手和四次揮手)

2022-07-09 21:12:17 字數 4133 閱讀 9423

寫到最後發現我描述的挺水的,這個老哥的用語比較專業一點  (老哥這篇有些許錯別字

大家可以看看它的.  看我的這篇可能會比較好理解一點,畢竟都是大白話

三次握手!

三次握手其實不準確。在官方文件中對於tcp連線,是用握手 handshake 來描述整個tcp連線  建立的過程。

只握一次手就可以建立tcp連線。那麼為什麼說是三次握手建立連線呢?  其實它的三次是傳送 三個報文,我們可以說是三報文握手

①一開始客戶機和伺服器都處於關閉狀態,客戶機主動開啟,向伺服器傳送乙個報文。這個報文攜帶著  syn = 1 (同步)和seq = x (乙個序列號,有各自的序列號,會不斷的增加)

此時客戶端處於 :syn-sent狀態

ps:大概看一下

同步syn:連線建立時用於同步序號。當syn=1,ack=0時表示:這是乙個連線請求報文段。若同意連線,則在響應報文段中使得syn=1,ack=1。因此,syn=1表示這是乙個連線請求,或連線接受報文。syn這個標誌位只有在tcp建產連線時才會被置1,握手完成後syn標誌位被置0。

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

② 然後我們的伺服器就 被動開啟,處於監聽狀態,等待客戶機傳送第乙個握手的報文。  

收到客戶機傳送的報文後,就會立刻向客戶機傳送乙個確認報文--------------- 

ack =1 ,syn = 1,seq = y, (小寫)ack =  x +  1

(大寫)ack是確認位,如果為1,**確認報文有效 .如果為0,則可以直接忽略,是沒有意義的

此時服務端處於syn-recv狀態

③這次的報文也有ack = 1,確認位有效,ack = y + 1 ,是確認報文

就是'  我 確認 我 收到了你的 確認報文 '   

就是我們客戶端,確認,服務端傳送的確認報文  我們客戶端收到了 

就是  伺服器端,用來確認客戶端傳送的用來建立連線的報文,我服務端收到了,那我服務端發給你客戶端的這個確認報文,你客戶端收到了沒有呢?

over  此時客戶端伺服器處於 established(tcp連線成功狀態)

細節:  ①seq  = x 到 ③seq = x + 1 說明客戶機在傳送③報文之前,期間是沒有再傳送其他報文

然後伺服器收到確認報文後,就建立了tcp連線  

有個疑問?明明執行①②的時候,tcp連線就可以建立了,那為什麼客戶端還有再次傳送乙個確認報文過去呢?

是因為①這樣乙個請求報文,可能會在傳送途中就失效了。這個失效不是說它 沒有作用了。

而是說  由於網路中某種原因,導致這個請求報文在網路中發生了  阻塞滯留,  但是tcp連線有乙個超時重傳機制

那麼①請求報文沒有到達的話,服務端就沒有收到。收不到這一條 ,服務端就會認為剛剛的①請求報文沒有發出去,那客戶端就會再次傳送一遍請求報文。

而剛剛那條請求報文就滯留在網路中。  客戶端再次傳送一條同樣的建立tcp連線的請求,這次服務端就收到了,然後  進行②確認     ③確認,這樣就建立tcp連線了

就在我們美滋滋建立tcp連線成功,用完了連線後,就銷毀掉了

然而剛剛滯留在網路中的那條  連線,可能我們的網路突然又通暢了,那剛剛那條連線又生效了,又到達了伺服器

伺服器收到了,就會再次給客戶端傳送確認報文 。  如果沒有③這一次確認報文,那麼tcp連線就建立了。

但是這條連線 我們不需要這次建立。因為我們之前已經重新 傳了一次請求報文,建立了連線,並釋放了。

所以沒有③就會重新建立一次連線,我們不需要這次連線。

有了③之後,伺服器傳送過來的確認報文,我客戶端這邊 收到後會說:我沒有給你傳送啊。

那麼就不會處理剛剛那條  '連線'

四次揮手

關閉之前都是建立狀態

①客戶端傳送  『連線釋放報文』,頭部攜帶的  fin =1,seq  = u   序列值為u      終止fin:用來釋放乙個連線。fin=1表示:此報文段的傳送方的資料已經傳送完畢,並要求釋放運輸連線

②服務端收到報文後,知道客戶端需要斷開連線。  那我給你傳送乙個確認報文,ack = 1,代表確認有效    seq 為 v , ack = u +1

客戶端收到報文, 客戶端  ---》服務端  這個方向的tcp連線已經斷開,已經失效了

而            客戶端  《---   服務端 這個方向還是可以連線的 

③ 但是我們服務端可能還要資料沒有傳遞過去,就需要重新傳送報文, fin = 1,ack = 1,seq = w, ack = u+1   細節:①的seq = v  ③的seq = w  正常都是+1,v到w說明中間不連續

這次是  伺服器要斷開  對客戶端的連線

④  伺服器端可能沒有收到我們的④確認報文, 伺服器就會認識是自己傳送的③我們沒有收到,那麼服務端就會再次傳送③,我要關閉了。這就是為啥要設定2msl 最大報文生成時段

要不然客戶端都已經關閉了,那你服務端還傳送個錘子?

客戶端收到伺服器的連線釋放報文後,必須發出確認,ack=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了time-wait(時間等待)狀態。注意此時tcp連線還沒有釋放,必須經過2msl(最長報文段壽命)的時間後,當客戶端撤銷相應的tcb後,才進入closed狀態。

【問題1】為什麼連線的時候是三次握手,關閉的時候卻是四次握手?

答:因為當server端收到client端的syn連線請求報文後,可以直接傳送syn+ack報文。其中ack報文是用來應答的,syn報文是用來同步的。但是關閉連線時,當server端收到fin報文時,很可能並不會立即關閉socket,所以只能先回覆乙個ack報文,告訴client端,"你發的fin報文我收到了"。只有等到我server端所有的報文都傳送完了,我才能傳送fin報文,因此不能一起傳送。故需要四步握手。

【問題2】為什麼time_wait狀態需要經過2msl(最大報文段生存時間)才能返回到close狀態?

答:雖然按道理,四個報文都傳送完畢,我們可以直接進入close狀態了,但是我們必須假象網路是不可靠的,有可以最後乙個ack丟失。所以time_wait狀態就是用來重發可能丟失的ack報文。在client傳送出最後的ack回覆,但該ack可能丟失。server如果沒有收到ack,將不斷重**送fin片段。所以client不能立即關閉,它必須確認server接收到了該ack。client會在傳送出ack之後進入到time_wait狀態。client會設定乙個計時器,等待2msl的時間。如果在該時間內再次收到fin,那麼client會重發ack並再次等待2msl。所謂的2msl是兩倍的msl(maximum segment lifetime)。msl指乙個片段在網路中最大的存活時間,2msl就是乙個傳送和乙個回覆所需的最大時間。如果直到2msl,client都沒有再次收到fin,那麼client推斷ack已經被成功接收,則結束tcp連線。

【問題3】為什麼不能用兩次握手進行連線?

答:3次握手完成兩個重要的功能,既要雙方做好傳送資料的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被傳送和確認。

現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作為例子,考慮計算機s和c之間的通訊,假定c給s傳送乙個連線請求分組,s收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,s認為連線已經成功地建立了,可以開始傳送資料分組。可是,c在s的應答分組在傳輸中被丟失的情況下,將不知道s 是否已準備好,不知道s建立什麼樣的序列號,c甚至懷疑s是否收到自己的連線請求分組。在這種情況下,c認為連線還未建立成功,將忽略s發來的任何資料分 組,只等待連線確認應答分組。而s在發出的分組超時後,重**送同樣的分組。這樣就形成了死鎖。

【問題4】如果已經建立了連線,但是客戶端突然出現故障了怎麼辦?

tcp還設有乙個保活計時器,顯然,客戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,伺服器就會傳送乙個探測報文段,以後每隔75秒鐘傳送一次。若一連傳送10個探測報文仍然沒反應,伺服器就認為客戶端出了故障,接著就關閉連線

TCP建立連線三次握手和釋放連線四次握手

尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下 tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的 順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個...

TCP建立連線三次握手和釋放連線四次握手

尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個報文...

TCP建立連線三次握手和釋放連線四次握手

尊重在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個報文段指...