如圖:
1. 請求端傳送乙個syn到伺服器的相應埠,以及初始序號isn
2. 伺服器傳送包含伺服器的初始序號的syn作為應答,同時確認序號設定為客戶的isn+1
3. 客戶將確認序號設定為伺服器的isn+1
最大報文段長度(mss)
同時開啟
一般情況下,連線建立時是一方傳送syn,另一方傳送syn+ack, 但極個別情況下,有可能兩個應用程式幾乎同時向對方傳送syn,這就叫做同時開啟。同時開啟需要雙方都使用彼此熟知的埠,而不是一般情況下只需要客戶使用伺服器的知名埠。
tcp的同時開啟的狀態變遷圖如下:
兩端幾乎同時傳送syn,並進入syn_sent狀態。當每一端收到syn時,狀態變為syn_rcvd,同時它們都再發syn並對收到的syn進行確認。當雙方都收到syn及相應的ack時,狀態都變遷為established。
呼入連線請求佇列
有可能出現當伺服器在建立乙個新的程序時,或作業系統正忙於處理優先順序更高的程序時,到達多個連線請求,當伺服器處於忙時,tcp是如何處理這些呼入的連線請求?
在伯克利的tcp實現中採用以下規則:
1. 正等待連線請求的一端有乙個固定長度的連線佇列,該佇列中的連線已被tcp接受(即三次握手已完成),但還沒有被應用層所接受。注意區分tcp接受乙個連線是將其放入佇列,而應用層是將其從該佇列中移出。
2. 應用層將指明該佇列的最大長度,這個值稱為積壓值。它的取值範圍是0~5之間的整數。
3. 當乙個連線請求到達時,tcp使用乙個演算法,來確定是否接收這個連線。
4. 如果對於新的連線請求,該tcp監聽的端點的連線佇列中還有空間,tcp模組將對這個syn進行確認並完成連線的建立。但應用層只有在三次握手中的第三個報文段才能知道這個新連線。另外,當客戶程序的主動開啟成功但伺服器的應用層還不知道這個新的連線時,它可能會認為伺服器程序已經準備好接收資料了(如果發生這種情況,伺服器的tcp僅將接收的資料放入緩衝佇列)。
5. 如果對於新的連線請求,連線佇列已沒有空間,tcp將不理會收到的syn,也不發回任何報文段(即不發回rst),如果應用層不能及時接受已被tcp接受的連線,這些連線可能佔滿整個連線佇列,客戶的主動開啟將最終超時。
當佇列已滿時,tcp將不理會收到的syn,也不發回任何報文段(即不發回rst),因為這是乙個軟錯誤,而不是乙個硬錯誤。通常佇列已滿是由於應用程式或作業系統忙造成的,這樣可防止應用程式對傳入的連線進行服務。這個條件在很短的時間內可以改變。但如果伺服器的tcp以系統復位作為響應,客戶程序的主動開啟將被廢棄。由於不應答syn,伺服器程式迫使客戶tcp隨後重傳syn,以等待連線佇列有空間接受新的連線。
既然乙個tcp連線是全雙工的(即資料在兩個方向上都能傳遞),因此每個方向都必須單獨進行關閉。這原則就是當一方完成它的資料傳送任務後就能傳送乙個fin來終止這個方向上的連線。當一端收到乙個fin,它必須通知應用層另一端已經終止了那個方向的資料傳送。
如下圖:
半關閉tcp提供了連線的一端在結束它的傳送後還能接收來自另一端資料的能力。這就是所謂的半關閉。
如下圖:
2msl等待狀態
time_wait狀態也稱為2msl等待狀態。每個具體tcp實現必須選擇乙個報文段最大生存時間msl。它是任何報文段被丟棄前在網路內的最長時間。
為什麼要有time_wait狀態?
- 因為終止連線的一方傳送的最後的乙個ack可能會丟失,另一端超時並重發最後的fin, 這樣終止連線的一方可以再次傳送最後的ack
為什麼是2msl?
- 最後乙個ack存在的時間最多為msl,如果ack丟失,然後接收端超時並重發fin,這個fin最多存在時間又是msl,而time_wait狀態需要等待這個連線中的所有分組都消失,所以需要等待2ml
- 2msl時間後這個連線的所有分組都會消失,不會干擾到接下來相同socket對建立的連線。
tcp在2msl等待期間,定義這個連線的插口(客戶的ip位址和埠號,伺服器的ip位址和埠號)不能再被使用,這個連線只能在2msl結束後才能再被使用。如果我們終止乙個已經建立連線的伺服器程式,並試圖立即重啟這個伺服器程式,伺服器程式不能把它的這個熟知埠賦值給它的端點,因為那個埠是出於2msl連線的一部分。
我們可以以-a標記來設定so_reuseaddr,這樣可以使伺服器程式使用之前的埠,但它不能主動開啟之前的相同埠的客戶程式,應為那個連線的插口對仍處於2msl等待狀態。但我們如果讓那個客戶程式來主動開啟這個伺服器程式是會成功的,因為大多數的伯克利實現支援乙個新的連線請求到達仍處於time_wait狀態的連線。
復位報文段
一般說來,無論何時乙個報文段發往指定的連線出現錯誤,tcp都會發出乙個復位報文段。
產生復位的幾種常見情況是:
- 到不存在的埠的連線請求;
- 異常終止乙個連線;
- 檢測半開啟連線。
如果一端已經關閉或異常終止連線而另一方卻還不知道,我們將這樣的連線成為半開啟連線。
同時關閉
兩邊都執行主動關閉也是有可能的,tcp協議也允許這樣的同時關閉。
如下圖:
為什麼伺服器對客戶fin的ack不和自己的fin合併(即終止連線不是三次握手)?
因為傳送客戶fin的ack通常是收到fin就立刻傳送,但這是伺服器不一定要關閉自己這端的連線,還可能需要傳送資料(半關閉),所以不一定要傳送fin。
分析處於time_wait狀態的主機收到使其進入此狀態的重複的fin時所發生的情況
傳送ack,重啟定時器。
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分節,它含有伺服器將在同...
TCP 連線的建立和終止
三路握手 建立乙個tcp連線時會發生下述情形。1 伺服器必須準備好接受外來的連線。這通常通過呼叫socket bind和listen這3個函式來完成的,我們稱之為被動開啟。2 客戶通過呼叫connect發起主動開啟。這導致客戶tcp傳送乙個syn 同步 分節,它告訴伺服器客戶將在 待建立的 連線中傳...