tcp是面向連線的協議。運輸連線是用來傳送tcp報文的。連線運輸就有三個階段,即:連線建立、資料傳送和連線釋放。
在tcp連線建立過程中要解決以下三個問題:
(1)要使每一方能夠確知對方的存在。
(2) 要允許雙方協商一些引數(如最大視窗值、是否使用視窗擴**項和時間戳選項以及服務質量等)。
(3) 能夠對運輸實體資源(如快取大小、連線表中的專案等)進行分配。
tcp的連線的建立採用客戶伺服器方式。主動發起連線建立的應用程序叫做客戶(client),而被動等待連線建立的應用程序叫做伺服器(server)。
tcp的連線建立
tcp建立連線的過程叫做握手,握手要在客戶和伺服器之間交換三個tcp報文段。看下圖。
假定主機a執行的是tcp客戶程式。而b執行tcp伺服器程式。最初兩端的tcp程序都處於closed(關閉)狀態。圖中在主機下面的方框分別是tcp程序所處的狀態。在本例中,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。tcp的標準規定,ack報文段可以攜帶資料。但如果不攜帶資料則不消耗序號,在這種情況下,下乙個資料報文段的序號仍是seq = x+1。這時,tcp連線已經建立,a進入established(已建立連線)狀態。
當b收到a的確認後,也進入established狀態。
上述的連線建立就就叫做三報文握手。
為什麼a最後還要傳送一次確認呢?這主要是為了防止已失效的連線請求報文段突然又傳送到了b,因而產生錯誤。
所謂」已失效的連線請求報文段「是這樣產生的。a發出連線請求,但因連線請求報文段丟失而未收到確認。於是a再重傳一次連線請求。後來收到了確認,建立了連線。資料傳輸完畢後,就釋放了連線。a共傳送兩個連線請求報文段,其中第乙個丟失,第二個到達了b,沒有」已失效的連線請求報文段「。
現在假定出現了一種異常情況,即a發出的第乙個連線請求報文段並沒有丟失,而是在某些網路結點長時間滯留了,以致延誤到連線釋放以後某個時間才到達b。本來這是乙個早已失效的報文段。但b收到此失效的連線請求報文段後,就誤認為a又發出了一次新的連線請求。於是就向a發出確認報文段,同意建立連線。假定不採用報文握手,那麼只要b發出確認,新的連線就建立了。
由於現在a並沒有發出建立連線的請求,因此不會理睬b的確認,也不會向b傳送資料。但b卻認為新的運輸連線已經建立了,並一直等待a發來資料。b的許多資源就這樣白白浪費了。
採用三報文握手的方法,可以防止上述現象的發生。例如在剛才的異常情況下,a不會向b的確認發出確認。b由於收不到確認,就知道a並沒有要求建立連線。
tcp的連線釋放
資料傳輸結束後,通訊的雙方都可以釋放連線。現在a和b都處於established狀態。(下圖),a的應用程序先向其tcp發出連線釋放報文段,並停止再傳送資料,主動關閉tcp連線。a把資料釋放報文段首部的終止控制符fin置1.其序號seq = 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(根據tcp標準,前面傳送過的fin報文段要消耗乙個序號)。然後進入到time-wait(時間等待)狀態。請注意,現在tcp連線還沒有釋放掉。必須經過時間等待計時器(time-wait timer)設定的時間2msl後,a才進入到closed狀態。時間msl叫做最長報文段壽命(maximum segment lifetime),rfc793建議設為2分鐘,對於現在的網路,msl=2分鐘可能太長了一些。因此tcp允許不同的實現可根據具體情況使用更小的msl值。因此,從a進入到time-wait狀態後,要經過4分鐘才能進入到closed狀態,才能開始建立下乙個新的連線。當a撤銷相應的傳輸控制塊tcb後,就結束了這次的tcp連線。
第一、為了保證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狀態。
第二、防止」已失效的連線請求報文段「出現在本連線中。a在傳送完最後乙個ack報文段後,再經過時間2msl,就可以使本連線的時間內所產生的所有報文段都從網路中消失。這樣就可以使下乙個新的連線中不會出現這種舊的連線請求報文段。
b只要收到了a發出的確認,就進入closed狀態。同樣,b在撤銷相應的傳輸控制塊tcb後,就結束了這次的tcp握手。注意,b結束tcp連線的時間要比a早一些。
上述就是tcp連線釋放過程中的四報文握手。
除時間等待計時器外,tcp還設有乙個保活計時器(keepalive timer)。設想有這樣的情況:客戶已主動與伺服器建立了tcp連線。但後來客戶端的主機突然出故障。顯然,伺服器以後就不能再收到客戶發來的資料。因此,應當有措施使伺服器不要再白白等待下去。這就是使用保活計時器。伺服器每收到一次客戶的資料,伺服器就傳送乙個探測報文段,以後則每隔75秒鐘傳送一次。若一連傳送10個探測報文段後仍無客戶的響應,伺服器就認為客戶端出了故障,接著就關閉這個連線。
tcp的有限狀態機
TCP連線管理
tcp是面向連線的協議,因此每個tcp連線都有三個階段 連線建立 資料傳送和連線釋放。tcp連線的管理就是使運輸連線的建立和釋放都能正常進行。在tcp連線建立的過程中,要解決以下三個問題 要使每一方都能確知對方的存在。要允許雙方協商一些引數 如最大視窗值 是否使用視窗擴 項 時間戳選項以及服務質量等...
TCP 連線管理
本節將介紹一條tcp連線是如何建立和拆除的。此處假設客戶機a上面的乙個程序想要和服務 器b上的乙個程序建立一條tcp連線。本文前面介紹的是比較正常的連線和拆除,特殊的會在後面介紹。第一步客戶機a的tcp會向伺服器的tcp傳送乙個不包含應用層資料的資料的tcp報文段。該報文段中首部標誌位s yn被置為...
TCP連線管理
一些基本的概念可以先看另一篇部落格 這篇直接對tcp連線過程做筆記 1.tcp連線詳細過程 假設執行在主機 客戶 的乙個程序想跟另一台主機 伺服器 上程序建立乙個連線 第一步 客戶端的tcp首先向服務端的tcp傳送乙個特殊的tcp報文段。該報文段不包含應用層資訊。報文段的syn 標誌位 置1。因此這...