1. 程式人生 > >TCP/UDP面試總結

TCP/UDP面試總結

TCP協議使用三握四揮、流量控制、擁塞控制三大機制來保證可靠性傳輸

1.TCP三次握手四次揮手:

1.三次握手:

這裡寫圖片描述
三次握手的過程:
首先伺服器和客戶端都處於Closed狀態。
而要進行連線的話,客戶端首先向伺服器傳送請求連線的TCP報文,報文中標誌位SYN=1,表示當前報文為請求建立連線的報文,seq=x 為當前報文的序號,之後客戶端處於syn-sent狀態。
而接收到請求建立連線報文的伺服器會處於listen狀態,此時伺服器向客戶端傳送接受TCP連線的TCP響應報文,報文中標誌位SYN=1,表示當前報文為接受請求連線的報文,ACK=1表示ack確認號生效。ack=x+1表示前x個報文已經收到,下次從x+1開始傳送,seq=y 表示自己的序號為y,之後服務端處於syn-rcvd狀態。
客戶端收到響應報文後再次傳送確認,ACK=1讓ack生效,ack=y+1,表示前y個收到,下次從y+1開始傳送,seq=x+1
之後客戶端和服務端都處於established狀態,表示已經建立好連線。

注意:第一、二次握手時會消耗一個序列號,用來表示該報文段,第三次握手如果帶資料就消耗序列號,如果不帶資料就不消耗序列號。從wireshark抓包中也能看出來。

為什麼要三次握手,兩次不行嗎?
結論:
為了防止已經失效的連線請求突然再發到服務端,然後服務端一直等待,浪費資源。
模擬場景:
假設只有兩次,客戶端向伺服器傳送請求建立連線的報文,但是這個報文再傳輸過程中在某個網路節點滯留了很長時間,甚至到連線釋放以後才到達服務端,導致其失效,那麼這個失效的報文服務端收到之後誤認為是一個新的請求建立連線的報文然後向客戶端傳送確認,這樣在兩次握手的前提下,一個新的連線就建立成功了,但是客戶端不會理會這樣的失效報文帶來的確認,那麼服務端就會一直在等待,浪費資源。

2.四次揮手

這裡寫圖片描述
四次揮手的過程:
TCP是一個全雙工模式,所以在斷開連線的時候是單方面進行斷開,但是如果真正要斷開連線則需要客戶端和服務端都斷開,連線才釋放。
首先,客戶端和服務端都處於established已連線狀態。
這時,客戶端向伺服器傳送斷開連線的請求,FIN=1表示這是一個斷開連線的請求,seq=x表示當前報文的序列號。之後客戶端將處於fin-wait1的狀態。
接收到客戶端斷開連線的請求,伺服器傳送確認,ACK=1,ack=x+1表示前x個都收到了,seq=y表示當前報文的序列號。之後服務端處於close-wait狀態。
此時,客戶端單方面斷開,不能再發送資料,但能接收到伺服器發來的資料,在伺服器發資料的這段時間客戶端處於fin-wait2狀態,伺服器處於close-wait狀態。
伺服器資料傳送完傳送請求斷開連線的報文,fin=1,ACK=1,ack=x+1表示上次客戶端傳送的確認報文收到了,seq=z表示當前報文序列號。之後服務端處於last-ack狀態。
客戶端收到服務端開啟的斷開連線的請求,則傳送確認給服務端,ACK=1,ack=w+1表示前w個報文都收到了,seq=x+1,之後客戶端處於time-wait狀態。
服務端收到確認斷開連線,處於closed狀態。
然而服務端要等2MSL才會真正斷開連線處於closed狀態。
只有兩端都處於closed狀態,此次連線才會釋放。

為什麼需要四次揮手?
結論:
為了保證資料的完全傳輸。
解釋:
TCP是全雙工模式,是單方面斷開連線,只有雙方都斷開才會釋放本次連線。
那麼當客戶端請求斷開連線,伺服器收到立馬回覆確認,只是表明伺服器知道客戶端沒有資料傳送了,但是伺服器本身還是可以繼續發資料接收資料的。此時,客戶端會處於fin-wait半關閉狀態,也就意味著它不能傳送資料但是依舊能接收資料。只有當服務端傳送完資料之後也請求斷開連線,客戶端收到立馬回覆確認之後伺服器才能斷開,而這時,客戶端等待2msl之後也斷開。兩端都關閉連線,全雙工TCP連線真正釋放。

注意:實際上也很有可能是三次揮手。因為如果服務端沒有資料要傳送的話就可以在客戶端請求斷開連線之後,服務端傳送確認同時也請求斷開連線,FIN和ACK同時傳送,這時客戶端接收並關閉連線,兩端都關閉連線,本次連線釋放。

為什麼需要等待2MSL才關閉連線?
MSL:最長報文段壽命,也就是對TCP報文段生存時間的限制。
作用:1.保證A最後一個ack報文可以到達B
2.防止已失效的連線請求報文段出現在本連線
解釋:最後一次客戶端傳送給服務端確認,如果客戶端一旦傳送確認就關閉連線的話,它不會收資料也不會發資料,就不能確定這個確認報文是否真正傳送給服務端,所以不能立馬關閉連線。工作流程是這樣的:第三次揮手服務端請求斷開連線,並且為該報文啟動超時重傳,客戶端接收到斷開連線的請求不會關閉連線並且傳送確認報文,隔一段時間之後,如果服務端的重傳計時器到時,說明客戶端的確認報文並未到達,那麼重新發送這個斷開連線的請求報文,從而保證最後一個客戶端向伺服器傳送的確認真的可以收到。因此客戶端需要等待,等待時間為FIN傳輸時間+重傳計時器啟動的重傳時間,保守設定為2MSL。
同時如果是一個已失效的連線請求的報文段,服務端不會再理會更不會確認。

3.TCP擁塞控制

作用:防止過多的資料諸如網路,使網路負載過大,讓網路能夠承載現在的負荷,實現供求平衡
控制方法:
接受視窗RWin – 根據接收方自身讀取速度以及接收快取的大小來設定(在緩衝區存在)
擁塞視窗CWin – 傳送端根據自己估計的網路擁塞成都設定的視窗值(假想的實際上不存在)
設定原則:
網路沒有擁塞,擁塞視窗設定大一些保證更多的資料在網路條件好的時候發出去,
網路出現擁塞,擁塞視窗就小一些,以便當前網路上注入的資料少一些,
從而保證傳輸。
傳送視窗的上限值 = Min[ CWin,RWin ]
傳送端傳送多少資料以接收視窗和擁塞視窗中較小的為基準
當 RWin < CWin 時,是接收端的接收能力限制傳送視窗的最大值。
當 RWin > CWin時,則是網路的擁塞情況限制傳送視窗的最大值。
擁塞控制具體實現:
這裡寫圖片描述
1.慢啟動:指數增長,對擁塞視窗進行增加,保證儘可能的傳輸資料,每次收到一個確認就將視窗增大,增加到閾值就進入擁塞避免。
2.擁塞避免:使用加法增大演算法,每經過一個往返時間RTT才會將擁塞視窗+1而不是加倍,當增加到當前網路能夠承受的最大值的時候就要進行乘法減小演算法,將閾值變成當前最大視窗(網路能夠負載的最大能力)的一半,然後再將擁塞視窗減到1,重新進行慢啟動,擁塞避免的過程
3.快重傳:收到三個重複確認,不用等到重傳計時器到期就直接傳送丟失的報文
4.快恢復:一旦發生丟失報文的情況,就悲觀的認為當前網路已經到了負載能力最大的地步,就直接開始執行擁塞避免,而不用等到慢啟動到達門限值之後再啟動擁塞避免。

4.TCP流量控制

簡述:就是給返回報文欄位中新增一個流量視窗大小的欄位,從而告知傳送方,下一次傳送資料的時候需要根據流量視窗的大小來發送資料,從而防止傳送方傳送過快而接收方根本讀不過來。
實現流量控制的方法:
序號,確認,超時重傳,滑動視窗等可靠性傳輸機制
滑動視窗:傳送方的緩衝區一部分是視窗,那麼窗口裡放的資料是允許傳送的資料和已傳送但未確認的資料,一旦傳送並確認,視窗就會向傳送方方向挪動,以便傳送下一個資料。
接收方的緩衝區同樣有一部分是視窗,存放的是允許接收和已接收但未確認的資料,一旦接收並確認,接收視窗就會向傳送方方向(相反於自身方向)滑動。
傳送視窗滿就停止:當接收方一直不確認,傳送方一直髮送允許傳送的資料,傳送視窗中就全部都是已傳送但未確認的資料,傳送視窗就會變滿,此時就停止傳送。
接收方接收能力弱:接收方來不及接收資料就會通知傳送方縮小視窗。
亂序報文解決:當接收方接收到亂序的報文會先將它存在視窗中並啟動超時重傳,等待發送方傳送缺少的資料,最後再進行重組。
丟失報文解決:傳送過程中報文丟失,接收方無法確認,那傳送方就會一直髮送,直到傳送方視窗變滿就會重新把丟失的報文發一遍。
這裡寫圖片描述
上述情況產生的問題:
RWin=0是因為接收方緩衝區滿了,就是讀取比較慢,等接收方讀取後,接收方緩衝區就空下來,
這時候接收方向傳送方傳送RWin=400,但是很不巧這個報文段丟了,傳送方一直在等待接收方說它空下來的訊息,但是接收方不知道自己之前傳送的丟了,所以也一直在等待發送方傳送資料?
尷尬。。。怎麼辦?
別擔心,持續計時器!!!!
只要TCP連線的一方收到對方的零視窗通知,就啟動持續計時器來預防發生上述問題。
工作原理:若持續計時器設定的時間到期就傳送一個視窗探測報文段攜帶一個位元組的資料。
就是說接收方給傳送方說:你等下再發,我這視窗滿了,我要是視窗空下來我就給你說。
傳送方就一直等著也不是辦法,所以就主動給接收方打個電話問一下:你看現在行不行?
接收方要是視窗空下
來就給傳送方傳送確認報文段也就是當前的視窗值:
如果確認報文段中視窗欄位值為0則傳送方就再設定持續計時器,
不是0就繼續進行正常的傳送和接收
當然如果老是0,傳送方就不自己打電話問了,就設定一個週期,週期性傳送探測

5.TCP和UDP區別

6.如何實現UDP可靠通訊?

為什麼要可靠?TCP在網路環境下要麼無法提供正常的通訊質量,要麼成本過高,所以我們在保證通訊的時延和質量的條件下儘量降低成本從而改造UDP
思想:儘量讓UDP往TCP的特性靠,同時也具有自己傳輸快,傳輸量大的特點。
做重傳機制(分為兩種):
傳送者發起重傳:(接收者如果收到報文要向傳送者傳送確認)
對於傳送者發起的方式,一般情況下接收者會發送一個訊息包的確認。傳送者維護一個計時器並重傳那些在某個確定的時間段裡沒有收到確認的訊息包。這一型別的協議容易引起傳送者溢位,因為要確認每一個傳送的訊息包。這種溢位現象被稱為傳送者(或者ACK)內爆。
接受者發起重傳:(接收者通過序號檢查有沒有報文丟失,從而讓傳送者重傳)
對於接收者發起的方式,通訊雙方的接收者負責錯誤檢測。在這個方式裡,序列號被用於檢測訊息包丟失。當檢測到訊息包丟失,接收者請求傳送者重傳訊息包。採用這種方法,如果訊息包沒有到達任何一個接收者,傳送者容易因NACK溢位。這會引起傳送者的負載過高和過多的重傳。這種現像被稱為NACK內爆。Ramakrishnan et al.提出可以使用定時器來限制訊息包重傳,從而避免NACK內爆。
RUDP
三角平衡關係:實時通訊中存在的三角平衡關係
這裡寫圖片描述
盡力可靠:通訊的接收方要求傳送方的資料儘量完整到達,但業務本身的資料是可以允許缺失的。例如:音視訊資料、冪等性狀態資料。
無序可靠:通訊的接收方要求傳送方的資料必須完整到達,但可以不管到達先後順序。例如:檔案傳輸、白板書寫、圖形實時繪製資料、日誌型追加資料等。
有序可靠:通訊接收方要求傳送方的資料必須按順序完整到達。
RUDP根據這三類需求以及制約關係來確定自己的通訊模型和機制,找到通訊的平衡點。
也是根據TCP的思想,使用重傳,擁塞控制,流量視窗,但具體實現完了再學習。。。。。

7.TCP長連線,短連線,保活,心跳包

TCP短連線:
客戶端想伺服器發起連線請求,伺服器接收到請求,然後雙方建立連線。
客戶端向伺服器傳送訊息,伺服器迴應客戶端,然後讀寫一次就完成了,這時候雙方任何一個都可以發起close操作。不過一般都是客戶端先發起close操作,原因是一般伺服器除特殊情況外不會回覆完客戶端之後立即關閉連線。短連線一般只會在客戶端/伺服器之間傳遞一次讀寫操作
優點:管理起來比較簡單,存在的連線都是有用的連線,不需要額外的控制手段
TCP長連線:
客戶端向伺服器發起連線請求,伺服器接收請求,雙方建立連線。客戶端與伺服器完成一次讀寫之後,他們之間的連線並不會主動關閉,後續的讀寫操作會繼續使用這個連線。
TCP保活:
為伺服器應用提供,伺服器應用需要知道客戶主機是否崩潰。如果客戶端已經消失,伺服器就保留了一個半開放的連線,保活功能就是試圖在伺服器端檢測到這種半開放的連線
如果一個給定的連線在兩個小時內沒有任何動作,則伺服器就向客戶傳送一個探測報文段,客戶主機必須處於以下四個狀態之一:
1.客戶主機依然正常執行,並從伺服器可達。客戶的TCP響應正常,而伺服器也知道對方是正常的,伺服器在兩小時後將保活定時器復位。
2.客戶主機已經崩潰,並且關閉或者正在重新啟動。在任何一種情況下,客戶的TCP都沒有響應。服務端將不能收到對探測的響應,並在75秒後超時。伺服器總共傳送10個這樣的探測 ,每個間隔75秒。如果伺服器沒有收到一個響應,它就認為客戶主機已經關閉並終止連線。
3.客戶主機崩潰並已經重新啟動。伺服器將收到一個對其保活探測的響應,這個響應是一個復位,使得伺服器終止這個連線。
4.客戶機正常執行,但是伺服器不可達,這種情況與2類似,TCP能發現的就是沒有收到探查的響應。
長連線和短連線的產生在於客戶端和伺服器採取的關閉策略
心跳包:
每隔一段時間(TCP預設2小時)固定發一次包(內容一般是很小的包或者只包含包頭)給客戶端,從而告訴伺服器客戶端還活著。只要send或者recv一下,結果為零,則為掉線