1. 程式人生 > >面試題:TCP三次握手、四次握手內容整理

面試題:TCP三次握手、四次握手內容整理

第一次握手:建立連線時,客戶端傳送syn包(syn=j)到伺服器,並進入SYN_SENT狀態,等待伺服器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;

第三次握手:客戶端收到服務器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手。

完成三次握手,客戶端與伺服器開始傳送

資料,在上述過程中,還有一些重要的概念:

未連線佇列

三次握手協議中,伺服器維護一個未連線佇列,該佇列為每個客戶端的SYN包(syn=j)開設一個條目,該條目表明伺服器已收到SYN包,並向客戶發出確認,正在等待客戶的確認包。這些條目所標識的連線在伺服器處於SYN_RECV狀態,當伺服器收到客戶的確認包時,刪除該條目,伺服器進入ESTABLISHED狀態。

 

關閉TCP連線:改進的三次握手

對於一個已經建立的連線,TCP使用改進的三次握手來釋放連線(使用一個帶有FIN附加標記的報文段)。TCP關閉連線的步驟如下:

第一步,當主機A的應用程式通知TCP資料已經發送完畢時,TCP向主機B傳送一個帶有FIN附加標記的報文段(FIN表示英文finish)。

第二步,主機B收到這個FIN報文段之後,並不立即用FIN報文段回覆主機A,而是先向主機A傳送一個確認序號ACK,同時通知自己相應的應用程式:對方要求關閉連線(先發送ACK的目的是為了防止在這段時間內,對方重傳FIN報文段)。

第三步,主機B的應用程式告訴TCP:我要徹底的關閉連線,TCP向主機A送一個FIN報文段。

第四步,主機A收到這個FIN報文段後,向主機B傳送一個ACK表示連線徹底釋放。

為什麼要採用三次握手,兩次不行嗎?

 

 

 

 

 

 

保活計時器:

設想有這樣的情況:客戶端已主動與伺服器建立了TCP連線,但後來客戶端的主機突然出現故障。

通常設為2小時。若2小時沒有收到客戶端的資料,伺服器就傳送一個探測報文段,以後則每隔75分鐘傳送一次。若一連發送10個探測報文段後仍無客戶端的響應,伺服器就認為客戶端出現了故障,接著就關閉這個連線。

 

 

 

 

為什麼連線的時候是三次握手,關閉的時候卻是四次握手?

答:因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能傳送FIN報文,因此不能一起傳送。故需要四步握手。

 

為什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網路是不可靠的,有可以最後一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。