先看看tcp的狀態變遷圖(tcp/ip詳解上面的原圖,來自google)
下面就圖中涉及到的問題做一些說明。
下面是tcp連線建立與終止的時候的時序圖:
在tcp/ip協議中,tcp協議提供可靠的連線服務,採用三次握手建立乙個連線
(1)第一次握手:建立連線時,客戶端a傳送syn包(syn=j)到伺服器b,並進入syn_send狀態,等待伺服器b確認。
(2)第二次握手:伺服器b收到syn包,必須確認客戶a的syn(ack=j+1),同時自己也傳送乙個syn包(syn=k),即syn+ack包,此時伺服器b進入syn_recv狀態。
(3)第三次握手:客戶端a收到伺服器b的syn+ack包,向伺服器b傳送確認包ack(ack=k+1),此包傳送完畢,客戶端a和伺服器b進入established狀態,完成三次握手。
由於tcp連線是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料傳送任務後就能傳送乙個fin來終止這個方向的連線。收到乙個fin只意味著這一方向上沒有資料流動,乙個tcp連線在收到乙個fin後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
(1)客戶端a傳送乙個fin,用來關閉客戶a到伺服器b的資料傳送(報文段4)。
(2)伺服器b收到這個fin,它發回乙個ack,確認序號為收到的序號加1(報文段5)。和syn一樣,乙個fin將占用乙個序號。
(3)伺服器b關閉與客戶端a的連線,傳送乙個fin給客戶端a(報文段6)。
(4)客戶端a發回ack報文確認,並將確認序號設定為收到序號加1(報文段7)。
最大報文段長度(mss)表示tcp傳往另一端的最大資料的長度。當乙個連線建立的時候連線的雙方都要通告各自的mss。一般來說如果沒有分段發生,mss還是越大越好。報文段越大允許每個報文段傳送的資料就越多,相對ip和tcp首部有更高的網路利用率,對於乙太網mss的值一般為1460。
time_wait狀態也稱為2msl等待狀態。每個具體實現的tcp實現必須選擇乙個報文段最大生存時間msl(maximum segment lifetiem).它是任何報文段被丟棄前在網路內的最長時間。對於乙個具體的實現所給定的msl值處理的原則是:當tcp執行乙個主動關閉,並發回最後乙個ack,該連線必須在time_wait狀態停留的時間為2倍的msl。
time_wait狀態存在有兩個理由:
(1)可讓tcp再次傳送最後的ack以防這個ack丟失(另一端超時並重發最後的fin)。
2倍msl的原因是time_wait狀態的ack給lask_ack狀態的時間,還有假設這個ack丟失,那麼lask_ack狀態需要再次傳送乙個fin給time_wait狀態。為什麼這個狀態特殊呢,因為這個狀態是客戶端的最後乙個狀態,這個狀態結束後客戶端就會讓出這個埠,這個連線也就會結束了。如果在接收到fin客戶端進入time_wait狀態並傳送ack後客戶端立刻結束,那麼可能服務端沒有收到ack,如果這個時候客戶端的time_wait狀態結束,即使服務端再次重發fin也不會有ack訊號了,而是會傳送乙個rst(服務埠未使用)。
(2)允許老的重複分節在網路中消逝。
在連線處於2msl等待時,任何遲到的報文段將被丟棄。如果沒有這個狀態,而且又建立起來乙個新的連線,那麼上一次連線的重複分組(因為路由故障等原因沒有按時到達而重**送,如果還是原來的連線會丟棄重複分組的)可能在新的連線中再現。為了防止這一點,tcp不給處於time_wait狀態的連線發起新的化身(不能立刻建立新連線)。既然time_wait狀態的持續時間是2msl,這就足以讓某個方向上的分組最多存活msl秒即被丟棄。
對於來自某個連線的較早替身的遲到報文段,2msl等待可防止將他解釋成使用相同插口對的新連線的一部分,但這只有在處於2msl等待連線中的主機處於正常工作狀態時才有效。如果使處於2msl等待埠的主機出現故障,它會在msl秒內啟動,並立即使用這個埠,那麼可能在故障前從這個連線發出而遲到的報文段會錯誤的當作屬於重啟後新連線的報文段(伺服器端沒有關閉可能會傳送fin)。為了防止發生這種情況,tcp在重啟後msl內不能建立任何連線,稱為平靜時間。一般很少的實現遵守這一規則,因為大多數主機重啟的時間都比msl時間長。
在下面三種情況下會用到復位報文段
(1)對於udp當乙個資料報到達該埠的時候,該埠沒在使用,它將產生乙個icmp埠不可達的資訊,而tcp使用復位。
(2)傳送乙個復位報文段而不是fin來中途釋放乙個連線,有時候稱為異常釋放(abortive release)。異常釋放時傳送端丟棄任何待傳送資料並傳送復位報文段。接收rst的一方接收到rst報文段後不會導致另一端產生任何響應,根本不進行確認,收到後終止連線並通知應用層連線復位。
(3)當伺服器重新啟動的時候,會丟失復位前的所有資訊,因此它不知道資料報文段中提到的連線,tcp的處理原則是接收方以復位作為應答。
當作業系統忙的時候,到達多個連線請求,在伯克利的tcp實現中採用以下規則:
(1)正等待連線請求的一端有乙個固定長度的連線佇列(其實為兩個,乙個未完成佇列,乙個已完成佇列,後面提到的佇列都為已完成佇列),該佇列中的連線已被tcp接受(三次握手已經完成),但還沒有倍應用層所接收。tcp接受乙個連線是將其放入這個佇列,而應用層接受連線是將其從該佇列中移出。
(2)應用層指出這個佇列的最大長度,這個值稱為積壓值(backlog),積壓值說明的是tcp監聽的端點已被tcp接受而等待應用層接受的最大連線數,這個積壓值對系統所允許的最大連線數或者併發伺服器所能併發處理的客戶數並無影響。
(3)對於新的連線請求,連線佇列中已沒有空間,tcp將不理會收到的syn也不傳送任何報文段(即不發回rst)。佇列滿通常是由於應用程式或作業系統忙造成的,這個條件可能在乙個很短時間內可以改變。如果伺服器的tcp以復位作為響應,客戶程序的主動開啟將被廢棄(如果伺服器程式沒有啟動就會遇到),由於不應答syn,伺服器程式迫使客戶tcp隨後重傳syn,以等待連線佇列有空間接受新的連線。當時不服務的目的是為了更快的提供服務,因為系統忙這個條件可能很快就消失,可以讓客戶端在多傳送幾次連線請求,而比直接讓連線復位更好。
監聽套接字與已連線套接字
accept的第一引數為監聽套接字描述符(由socket建立,隨後用作bind和listen的第乙個引數的描述符),稱它的返回值為已連線套接字描述符。
乙個伺服器通常僅僅建立乙個監聽套接字,他在該伺服器的生命週期內一直存在。核心為每個由伺服器程序接受的客戶連線建立乙個已連線套接字(tcp的三次握手已經完成),當伺服器完成對某個給定客戶的服務時,相應的已連線套接字就被關閉。
TCP建立和終止
本文參考了 unix網路程式設計 主要內容分為以下兩部分 1 tcp客戶端和伺服器一些典型事件概述 2 tcp連線的建立和終止 1 1.1 tcp客戶端和伺服器一些典型事件時間表如下 connect函式出錯時主要有以下幾種情況 1 tcp客戶未收到syn分節的響應,返回etimedout 2 對客戶...
TCP 連線的建立和終止
1.伺服器通過呼叫socket,bind和listen三個函式準備接受外來連線,稱為被動開啟。2.客戶通過呼叫connect發起主動開啟,導致客戶tcp傳送乙個syn同步分節,告訴伺服器將在連線中傳送的資料的初始序列號。syn分節不包含資料,只包含乙個ip首部,乙個tcp首部及可能的tcp選項。3....
TCP連線的建立和終止
一 tcp連線建立 三路握手 1 伺服器必現準備好接受外來的連線,即被動開啟。2 客戶通過呼叫connect發起主動開啟,這導致客戶tcp傳送乙個syn分節,它告訴伺服器客戶將在連線中傳送的資料的初始序列號。3 伺服器必須確認 ack 客戶的syn,同時自己也得傳送乙個syn分節,它含有伺服器將在同...