TCP的三次握手是過程是怎樣的?
- 請求端(客戶端)發起第一個SYN,執行主動開啟,表示想要連線服務端,同時指明初始序號(ISN,比如這裡的141553152)
- 服務端做出回應,指明自己的初始序號,執行被動開啟,同時將確認序號設定成對客戶端的初始序號加1,表示確認了客戶端的SYN
- 客戶端將確認序號設定成服務端的初始序號加1,表示確認了服務端的SYN
ISN:初始序號,可以看做是一個32位元的計數器,每4ms加1,詳見RFC 793
TCP的四次揮手過程是怎樣的?
- 請求端(客戶端)想斷開連線,於是發出一個FIN包
- 服務端接收到請求,在確認序號上對客戶端的序號加1表示已確認
- 服務端關閉自己的連線,發出一個FIN包
- 客戶端接收到請求,在確認序號上對服務端序號加1表示已經確認
TCP連線是全雙工的,每個方向都必須單獨關閉
建立連線時如果超時了會發生什麼事情?
出現場景
伺服器在客戶端建立連線時剛好斷電。可以看出客戶端進行了重試,但是重試之間的時間間隔第一次是5.81秒,而第二次間隔是24.00秒。
這種超時重試時間間隔對於BSD版的TCP軟體實現來講,是由於500ms的定時器存在。第一次的間隔一般在5.5-6秒任意時刻超時,而第二次一般穩定在24秒。這是由於TCP在500ms以內獲得系統控制的瞬間,可能系統會優先處理其它中斷,從而第一次計數器減1會發生在0-500ms的任意一個時刻。而每次TCP 500ms定時器被核心呼叫時都會修正,因而後續穩定
tos 0x10 表示IP資料包內的服務型別,這裡的值為DNS的udp查詢
異常終止連線會發生什麼事情?
連線一方傳送復位報文來中途釋放連線【正常是傳送FIN】
異常釋放的一端將返回RST報文段,收到的一方將終止連線,並通知應用層進行復位,接收方並不對RST報文進行確認。
什麼是TCP的半關閉?
TCP的一端結束髮送後,仍然能接收另一端傳送的資料。
應用場景
想僅進行一次排序的操作。流程為從客戶端讀取使用者輸入的檔案,從服務端進行排序,然後客戶端接收排序的結果。對於客戶端來講,當檔案傳輸完畢之後不會再傳送資料,此時可以直接關閉,而服務端需要先對資料拍完序,再做回應,此時客戶端要保持接收資料的能力,這樣就適合使用半關閉(服務端通知客戶端也可以使用另外1次TCP連線,但是半關閉可以省掉多餘1次的連線過程)
什麼是TCP的半開啟?
連線的一端已經關閉或異常終止,但是另一端確不知道這個情況。
出現場景
客戶端和服務端正在正常通訊的時候,突然伺服器斷電了,這個時候客戶端並不知道伺服器斷電,對於這種情況,如果伺服器立即恢復電源再立馬重啟,當客戶端在伺服器重啟之後傳送資料時,服務端則回覆復位標識,即TCP的標識位R設定為1,客戶端收到資訊,知曉連線終止
類似場景:客戶使用完自己的電腦,直接把電腦電源線拔了,這時伺服器並不知道客戶端已經消失,後續客戶端再開機又會建立新的連線,這樣導致伺服器會存在許多半開啟的連線
如果TCP兩端同時開啟會怎麼樣?
通訊雙方傳送的SYN同時到達對方,且一端傳送的埠和另一端要求接收的埠一樣。
出現場景
主機A應用程式使用本地埠7777,與主機B埠8888執行主動開啟,主機B應用程式則使用本地埠8888,與主機A埠7777執行主動開啟
報文狀態變遷如下
整個過程開啟需要4次報文段交換,tcp本身的設計保證,這種場景僅建立了1個連線
其它協議族可能建立兩條,比如OSI運輸層
如果TCP兩端同時關閉會怎麼樣?
通訊雙方都執行主動關閉。狀態變化如下:
交換的報文段和正常的關閉使用的數目一樣。
TCP的狀體變遷過程是怎樣的?
3次握手的狀態變遷
連線建立超時狀態變遷
同時開啟狀態變遷
4次揮手狀態變遷
同時關閉狀態變遷
收到RST的可能狀態變遷
RST發生一般是接收端收到的包很明顯和當前連線沒有啥關係,這時候就觸發RST包產生
- 由於某種未知因素,客戶端發出的SYN多次,但是服務端接收到的卻是舊的SYN,這時候客戶端發出RST,服務端收到RST重新建連線
- 處於半開啟狀態,連線已經建立的時候,突然客戶端掛了,這時當客戶端嘗試再次開啟連線或者服務端再次傳送資料都會讓服務端收到RST
上圖為客戶端CRASH然後客戶端重連,下圖為客戶端CRASH然後服務端向客戶端返回資料
從SYN_RECEVIED狀態進入FIN_WAIT_1狀態
此時沒有需要傳送的東西,佇列中也沒有未完成的東西需要傳送,就生成一個FIN包,傳送出去,斷開連線
有要傳送的東西,比如ack,就去建立連線
2MSL等待時間是什麼?
MSL(Maximum Segment Lifetime)是報文段的最大生存時間。
生存時間是有限的,由於TCP報文段是以IP資料包在網路內傳輸,而IP資料包通過TTL的跳數限制,因而報文段被丟棄之前,在網路內生存時間有限
當TCP執行主動關閉併發回最後一個ACK,該連線必須在TIME_WAIT狀態內等待2倍的MSL時間。
原因:1:TCP主動關閉端傳送的ACK如果丟失了,被動關閉端再次重發FIN,這時候的時間等待能夠使得TCP主動關閉端傳送最後的ACK不會丟失;2下次新的連線可能會複用同一個埠,如果由於網路延遲,老的資料才到,會與新資料發生混合,等待2MSL可以使得老資料完全消失
在2MSL時間段之內,定義這個連線的插口(客戶端IP和埠,服務端IP和埠),不能再被 被動斷開方使用
如果服務端的連線突然斷開再立馬重新啟動,伺服器的這個埠在2MSL時間內客戶端無法連線【這裡客戶端是被動斷開方】;同理如果是客戶端自己斷開,再立馬使用相同的埠,在2MSL時間內去連伺服器也是無法成功的【這裡伺服器是被動斷開方】。這種場景客戶端可以再隨便換一個埠即可,但是服務端的一般應用埠都是固定的,容易造成麻煩
如果多個請求同時到達服務端,服務端是如何處理的?
TCP伺服器會專門安排一個程式,它永遠處於LISTEN狀態,用來接收客戶端的請求,當請求被接收時,系統中的TCP模組就會建立一個處於ESTABLISHED狀態的程式
處於LISTEN狀態的程式不能接收資料包文段,處於ESTABLISHED狀態程式不能接收SYN報文段
伯克利TCP實現多連線處理規則為:
- 正等待連線請求一端有一個固定長度的連線佇列,佇列中的連線已被TCP接受,但是應用層還沒有感知
- 應用層指明改佇列的最大長度,它通常稱為積壓值(backlog),取值範圍是0-5
- 新連線到達時,如果連線佇列有空間,TCP模組將對SYN進行確認並完成連線建立。但應用層只有在3次握手的第3次報文段接收到後才知道這個新連線
- 新連線到達,但是連線佇列沒有空間,TCP模組不理會SYN,也不發回RST,如果應用層沒有及時接受已被該TCP接受的連線,連線佔滿,客戶端的主動開啟最終將超時
TCP接收連線是放入連線佇列,應用層接收連線是從佇列中移除
佇列的積壓數與伺服器能處理的最大連線數沒有關係