TCP是一個面向鏈接的協議。不管哪一方向另外一方發送數據以前,都必須先在雙方之間創建一條鏈接。鏈接建立與終止的狀態變化圖以下: 算法
網絡是不可靠的,數據包是可能丟失的
。假設沒有第三次確認,客戶端向服務端發送了 SYN,請求創建鏈接。因爲延遲,服務端沒有及時收到這個包。因而客戶端從新發送一個 SYN 包。回憶一下介紹 TCP 首部時提到的序列號,這兩個包的序列號顯然是相同的。假設服務端接收到了第二個 SYN 包,創建了通訊,一段時間後通訊結束,鏈接被關閉。這時候最初被髮送的 SYN 包剛剛抵達服務端,服務端又會發送一次 ACK 確認。因爲兩次握手就創建了鏈接,此時的服務端就會創建一個新的鏈接,然而客戶端以爲本身並無請求創建鏈接,因此就不會向服務端發送數據。從而致使服務端創建了一個空的鏈接,白白浪費資源。 TCP是雙通道,須要雙向肯定
。只有兩次握手,客戶端知道了服務器收到了,服務器不知道客戶端收到了,聯想打電話。通信系統中的占拜庭將軍問題。服務器
最大報文段長度(MSS)表示TCP傳往另外一端的最大塊數據的長度。當一個鏈接創建時,鏈接的雙方都要通告各自的MSS。在三次握手的時候SYN的TCP首部中的可選字段肯定。以太網的默認長度爲1460。微信
創建一個鏈接須要三次握手,而終止一個鏈接要通過4次握手。這由TCP的半關閉(half-close)形成的。一個TCP鏈接是全雙工(即數據在兩個方向上能同時傳遞),所以每一個方向必須單獨地進行關閉。 網絡
TCP提供了鏈接的一端在結束它的發送後還能接收來自另外一端數據的能力。如主動方處於fin_wait2狀態。併發
TIME_WAIT狀態也稱爲2MSL等待狀態。每一個具體TCP實現必須選擇一個報文段最大生存時間MSL( Maximum Segment Lifetime)。它是任何報文段被丟棄前在網絡內的最長時間。由於TCP報文段以IP數據報在網絡內傳輸,而IP數據報則有限制其生存時間的TTL字段。在實際應用中,對 I P數據報TTL的限制是基於跳數,而不是定時器。 在處於2MSL等待狀態的socket(客戶端IP與端口,服務器IP與端口)不能再被使用。但在實際的使用中,容許一個新的鏈接請求到達仍處於time_wait狀態的鏈接,只要新的序號大於該鏈接的前一個鏈接的最後序號。socket
下面是一次完整的tcp創建鏈接,發送數據,關閉鏈接過程 tcp
該過程爲,3次握手創建鏈接,一次數據發送,4次握手關閉鏈接操作系統
出現異常的時候,服務器一般經過復位報文來通告,復位報文爲tcp數據包類型設置爲rst。設計
當服務器端沒有開或網絡問題,會出現鏈接超時的狀況。抓包以下: code
在TCP通信中。若是通信雙方應爲某種緣由(如忽然斷電等)關閉鏈接時候一方(如A)沒有發送fin數據包。另外一端(如B)不知道對方已經關閉了鏈接。再次發送數據的時候,異常關閉的一方,可能會返回一個rst數據包。通知異常關閉。若是一方已經關閉或異常終止鏈接而另外一方卻還不知道,咱們將這樣的TCP鏈接稱爲半打開(Half Open)的。
兩個應用程序同時彼此執行主動打開的狀況是可能的。每一方必須發送一個SYN,且這些SYN必須傳遞給對方。這須要每一方使用一個對方熟知的端口做爲本地端口。同時打開的狀態遷移圖不一樣於正常狀態的三次握手,該狀況下須要進行4次握手。如圖:
咱們在之前討論過一方(一般但不老是客戶方)發送第一個FIN執行主動關閉。雙方都執行主動關閉也是可能的,TCP協議也容許這樣的同時關閉(simultaneous close)。在同時關閉的時候,雙方都進入time_wait狀態,如圖:
大多數的TCP服務器進程是併發的。當一個新的鏈接請求到達服務器時,服務器接受這個請求,並調用一個新進程來處理這個新的客戶請求。
一個併發服務器調用一個新的進程來處理每一個客戶請求,所以處於被動鏈接請求的服務器應該始終準備處理下一個呼入的鏈接請求。那正是使用併發服務器的根本緣由。但仍有可能出現當服務器在建立一個新的進程時,或操做系統正忙於處理優先級更高的進程時,到達多個鏈接請求。當服務器正處於忙時,TCP是如何處理這些呼入的鏈接請求?TCP有這樣一個隊列來臨時存放這些鏈接-接入鏈接請求隊列。處理方式以下:
都看到這裏了,要不要掃二維碼關注一下微信公衆號林灣村龍貓。