搞定網路協議 之三次握手四次揮手詳解

2021-09-01 13:07:56 字數 3800 閱讀 2080

tcp報文段首部格式:

序號:本報文段所傳送的資料的第乙個位元組的序號;

確認ack:佔1位,僅當ack=1時,確認號字段才有效。ack=0時,確認號無效;

同步syn:連線建立時用於同步序號。當syn=1,ack=0時表示:這是乙個連線請求報文段;

若同意連線,則在響應報文段中使得syn=1,ack=1。因此,syn=1表示這是乙個連線請求,或連線接受報文;

終止fin:用來釋放乙個連線。fin=1表示:此報文段的傳送方的資料已經傳送完畢,並要求釋放運輸連線。

tcp建立連線的過程叫做握手,握手需要在客戶和伺服器之間交換三個tcp報文段。

最初客戶端和服務端都處於closed(關閉)狀態。本例中a主動開啟連線,b被動開啟連線。

一開始,b的tcp伺服器程序首先建立傳輸控制塊tcb,準備接受客戶端程序的連線請求。然後服務端程序就處於listen(監聽)狀態,等待客戶端的連線請求。如有,立即作出響應。

a的tcp客戶端程序也是首先建立傳輸控制塊tcb。然後,在打算建立tcp連線時,向b發出連線請求報文段,這時首部中的同步位syn=1,同時選擇乙個初始序號seq=x。tcp規定,syn報文段(即syn=1的報文段)不能攜帶資料,但要消耗掉乙個序號。這時,tcp客戶程序進入syn-sent(同步已傳送)狀態

b收到連線請求報文後,如果同意建立連線,則向a傳送確認。在確認報文段中應把syn位和ack位都置1,確認號是ack = x + 1,同時也為自己選擇乙個初始序號seq = y。請注意,這個報文段也不能攜帶資料,但同樣要消耗掉乙個序號。這時tcp服務端程序進入syn-rcvd(同步收到)狀態

tcp客戶程序收到b的確認後,還要向b給出確認。確認報文段的ack置1,確認號ack = y +  1,而自己的序號seq = x + 1。這時ack報文段可以攜帶資料。但如果不攜帶資料則不消耗序號,這種情況下,下乙個資料報文段的序號仍是seq = x + 1。這時,tcp連線已經建立,a進入established(已建立連線)狀態

為什麼是三次握手,而不是兩次握手或者四次握手呢?

不可以兩次握手的原因:

為了防止已經失效的鏈結請求報文段突然又傳送到了b,因而產生錯誤。比如下面這種情況:a發出的第乙個連線請求報文段並沒有丟失,而是在網路結點長時間滯留了,以致於延誤到連線釋放以後的某個時間段才到達b。本來這是乙個早已失效的報文段。但是b收到此失效的鏈結請求報文段後,就誤認為a又發出一次新的連線請求。於是就向a發出確認報文段,同意建立連線。

對於上面這種情況,如果不進行第三次握手,b發出確認後就認為新的運輸連線已經建立了,並一直等待a發來資料。b的許多資源就這樣白白浪費了。

如果採用了三次握手,由於a實際上並沒有發出建立連線請求,所以不會理睬b的確認,也不會向b傳送資料。b由於收不到確認,就知道a並沒有要求建立連線。

不需要四次握手的原因:

有人可能會說a發出第三次握手的資訊後在沒有接收到b的請求就已經進入了連線狀態,那如果a的這個確認包丟失或者滯留了怎麼辦?

我們需要明白一點,完全可靠的通訊協議是不存在的。在經過三次握手之後,客戶端和服務端已經可以確認之前的通訊狀況,都收到了確認資訊。所以即便再增加握手次數也不能保證後面的通訊完全可靠,所以是沒有必要的。

資料傳輸結束後,通訊的雙方都可以釋放連線。現在a和b都處於established狀態

a的應用程序先向其tcp發出連線釋放報文段,並停止再傳送資料,主動關閉tcp連線。a把連線釋放報文段首部的終止控制位fin置1,其序號aeq = u(等於前面已傳送過的資料的最後乙個位元組的序號加1),這時a進入fin-wait-1(終止等待1)狀態,等待b的確認。請注意:tcp規定,fin報文段即使不攜帶資料,也將消耗掉乙個序號。

b收到連線釋放報文段後立即發出確認,確認號是ack = u + 1,而這個報文段自己的序號是v(等於b前面已經傳送過的資料的最後乙個位元組的序號加1).然後b就進入close-wait(關閉等待)狀態。tcp服務端程序這時應通知高層應用程序,因而從a到b這個方向的連線就釋放了,這時的tcp連線處於半關閉(half-close)狀態,即a已經沒有資料要傳送了,但b若傳送資料,a仍要接收。也就是說,從b到a這個方向的連線並未關閉,這個狀態可能會持續一段時間。

a收到來自b的確認後,就進入fin-wait-2(終止等待2)狀態,等待b發出的連線釋放報文段。

若b已經沒有要向a傳送的資料,其應用程序就通知tcp釋放連線。這時b發出的連線釋放報文段必須使fin=1。假定b的序號為w(在半關閉狀態,b可能又傳送了一些資料)。b還必須重複上次已傳送過的確認號ack = u + 1。這時b就進入last-ack(最後確認)狀態,等待a的確認。

a在收到b的連線釋放報文後,必須對此發出確認。在確認報文段中把ack置1,確認號ack = w + 1,而自己的序號seq = u + 1(前面傳送的fin報文段要消耗乙個序號)。然後進入time-wait(時間等待)狀態。請注意,現在tcp連線還沒有釋放掉。必須經過時間等待計時器設定的時間2msl(msl:最長報文段壽命)後,a才能進入到closed狀態,然後撤銷傳輸控制塊,結束這次tcp連線。當然如果b一收到a的確認就進入closed狀態,然後撤銷傳輸控制塊。所以在釋放連線時,b結束tcp連線的時間要早於a。

為什麼a在time-wait狀態必須等待2msl的時間呢?

1、為了保證a傳送的最後乙個ack報文段能夠到達b。這個ack報文段有可能丟失,因而使處在last-ack狀態的b收不到對已傳送的fin+ack報文段的確認。b會超時重傳這個fin+ack報文段,而a就能在2msl時間內收到這個重傳的fin+ack報文段。接著a重傳一次確認,重新啟動2msl計時器。最後,a和b都正常進入到closed狀態。如果a在time-wait狀態不等待一段時間,而是在傳送完ack報文段後立即釋放連線,那麼就無法收到b重傳的fin+ack報文段,因而也不會再傳送一次確認報文段,這樣,b就無法按照正常步驟進入closed狀態。

2、防止已失效的連線請求報文段出現在本連線中。a在傳送完最後乙個ack報文段後,再經過時間2msl,就可以使本連線持續的時間內所產生的所有報文段都從網路中消失。這樣就可以使下乙個連線中不會出現這種舊的連線請求報文段。

保活計時器:

除時間等待計時器外,tcp還有乙個保活計時器(keepalive  timer)。設想這樣的場景:客戶已主動與伺服器建立了tcp連線。但後來客戶端的主機突然發生故障。顯然,伺服器以後就不能再收到客戶端發來的資料。因此,應當有措施使伺服器不要再白白等待下去。這就需要使用保活計時器了。

伺服器每收到一次客戶的資料,就重新設定保活計時器,時間的設定通常是兩個小時。若兩個小時都沒有收到客戶端的資料,服務端就傳送乙個探測報文段,以後則每隔75秒鐘傳送一次。若連續傳送10個探測報文段後仍然無客戶端的響應,服務端就認為客戶端出了故障,接著就關閉這個連線。

TCP協議之三次握手四次揮手

tcp協議是可靠的傳輸 表現在2個方面 1.是保證資料報可以按照傳送的順序到達 2.另外一方面是保證資料報一定程度的正確性 後文詳解為什麼是一定程度上的正確性 其可靠性的實現則基於2點技術,一點是具有乙個crc校驗,這樣如果資料報中的某些資料出現錯誤可以通過該校驗和發現 另外一點是每個資料報都有乙個...

網路協議 三次握手 四次揮手

協議 網路協議為計算機網路中進行資料交換而建立的規則 標準或約定的集合。例如,網路中乙個微機使用者和乙個大型主機的操作員進行通訊,由於這兩個資料終端所用字符集不同,因此操作員所輸入的命令彼此不認識。為了能進行通訊,規定每個終端都要將各自字符集中的字元先變換為標準字符集的字元後,才進入網路傳送,到達目...

三次握手四次揮手協議

一 三次握手 三次握手用正常白話講就是 就這樣經過三次成功建立連線 至於為什麼要經過三報文握手建立連線呢?不是說只能這樣建立連線,只是因為這樣能避免很多建立連線的問題。它可以防止已失效的連線請求報文段突然又傳送到了服務端,因而產生錯誤。比如 client發出的第乙個連線請求報文段並沒有丟失,而是在某...