前言
TCP三次握手和四次揮手是面試題的熱門考點,它們分別對應TCP的連接和釋放程序
1.TCP通信包含那幾步?
TCP通信程序包括三個步驟:建立TCP連接通道,傳輸資料,斷開TCP連接通道

上圖主要包括三部分:*建立連接、傳輸資料、斷開連接,*
- 建立TCP連接很簡單,通過三次握手便可建立連接,
- 建立好連接后,開始傳輸資料,TCP資料傳輸牽涉到的概念很多:超時重傳、快速重傳、流量控制、擁塞控制等等,
- 斷開連接的程序也很簡單,通過四次握手完成斷開連接的程序
2.三次握手建立連接
第一次握手: 客戶端發送syn包(seq=x)到服務器,并進入SYN_SEND狀態,等待服務器確認;
第二次握手: 服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(seq=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手,
握手程序中傳送的包里不包含資料,三次握手完畢后,客戶端與服務器才正式開始傳送資料,理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去,
3.傳輸資料程序
- 超時重傳 超時重傳機制用來保證TCP傳輸的可靠性,每次發送資料包時,發送的資料報都有seq號,接收端收到資料后,會回復ack進行確認,表示某一seq 號資料已經收到,發送方在發送了某個seq包后,等待一段時間,如果沒有收到對應的ack回復,就會認為報文丟失,會重傳這個資料包,
- 快速重傳 接受資料一方發現有資料包丟掉了,就會發送ack報文告訴發送端重傳丟失的報文,如果發送端連續收到標號相同的ack包,則會觸發客戶端的快速重 傳,比較超時重傳和快速重傳,可以發現超時重傳是發送端在傻等超時,然后觸發重傳;而快速重傳則是接收端主動告訴發送端資料沒收到,然后觸發發送端重傳,
- 流量控制 這里主要說TCP滑動窗流量控制,TCP頭里有一個欄位叫Window,又叫Advertised-Window,這個欄位是接收端告訴發送端自己 還有多少緩沖區可以接收資料,于是發送端就可以根據這個接收端的處理能力來發送資料,而不會導致接收端處理不過來,滑動窗可以是提高TCP傳輸效率的一種機制,
- 擁塞控制 滑動窗用來做流量控制,流量控制只關注發送端和接受端自身的狀況,而沒有考慮整個網路的通信情況,擁塞控制,則是基于整個網路來考慮的,
4.四次揮手斷開連接
第一次揮手: 主動關閉方發送一個FIN,用來關閉主動方到被動關閉方的資料傳送,也就是主動關閉方告訴被動關閉方:我已經不會再給你發資料了(當然,在fin包之前發送出去的資料,如果沒有收到對應的ack確認報文,主動關閉方依然會重發這些資料),但此時主動關閉方還可以接受資料,
第二次揮手:被動關閉方收到FIN包后,發送一個ACK給對方,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),
第三次揮手: 被動關閉方發送一個FIN,用來關閉被動關閉方到主動關閉方的資料傳送,也就是告訴主動關閉方,我的資料也發送完了,不會再給你發資料了,
第四次揮手: 主動關閉方收到FIN后,發送一個ACK給被動關閉方,確認序號為收到序號+1,至此,完成四次揮手,
5.常見面試問題
【問題1】為什么連接的時候是三次握手,關閉的時候卻是四次揮手?
答:因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文,其中ACK報文是用來應答的,SYN報文是用來同步的,但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,“你發的FIN報文我收到了”,只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送,故需要四步握手,
【問題2】為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能回傳到CLOSE狀態?
答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網路是不可靠的,有可以最后一個ACK丟失,所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文,在Client發送出最后的ACK回復,但該ACK可能丟失,Server如果沒有收到ACK,將不斷重復發送FIN片段,所以Client不能立即關閉,它必須確認Server接收到了該ACK,Client會在發送出ACK之后進入到TIME_WAIT狀態,Client會設定一個計時器,等待2MSL的時間,如果在該時間內再次收到FIN,那么Client會重發ACK并再次等待2MSL,所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime),MSL指一個片段在網路中最大的存活時間,2MSL就是一個發送和一個回復所需的最大時間,如果直到2MSL,Client都沒有再次收到FIN,那么Client推斷ACK已經被成功接收,則結束TCP連接,
【問題3】為什么不能用兩次握手進行連接?
答:3次握手完成兩個重要的功能,既要雙方做好發送資料的準備作業(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手程序中被發送和確認,
現在把三次握手改成僅需要兩次握手,死鎖是可能發生的,作為例子,考慮計算機S和C之間的通信,假定C給S發送一個連接請求分組,S收到了這個分組,并發 送了確認應答分組,按照兩次握手的協定,S認為連接已經成功地建立了,可以開始發送資料分組,可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組,在這種情況下,C認為連接還未建立成功,將忽略S發來的任何資料分 組,只等待連接確認應答分組,而S在發出的分組超時后,重復發送同樣的分組,這樣就形成了死鎖,
【問題4】如果已經建立了連接,但是客戶端突然出現故障了怎么辦?
答:TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源,服務器每收到一次客戶端的請求后都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,服務器就會發送一個探測報文段,以后每隔75分鐘發送一次,若一連發送10個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接,
總結
小卷聊開發,一個專注于技術、面試,偶爾發點生活的公眾號,關注我,一起變強!!!

本文來自博客園,作者:SmallRoll(小卷),轉載請注明原文鏈接:https://www.cnblogs.com/smallroll/p/17176101.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545707.html
標籤:其他
上一篇:學習多執行緒的心得
