1. 程式人生 > >TCP的三次握手和四次揮手,以及相關的面試問題詳細解釋

TCP的三次握手和四次揮手,以及相關的面試問題詳細解釋

TCP的首部:

  TCP資料被封裝在一個IP資料報中,下圖中顯示了TCP首部的資料格式,如果不計任選欄位,他通常是20個位元組。

 

TCP段分析:

①.16位源和目的埠號:

每個TCP段:都包含 源端 和 目的端 的埠號。(用於尋找發端和收端的應用程序)。更好實現TCP分用和複用;這兩個值再加上IP首部中的 源端IP地址 和 目的端IP地址,能唯一確定一個TCP連線。

 

有時:一個IP地址 和 一個埠號 也稱為 一個 插口(socket)

           插口對(socket pair):包含客戶IP地址,客戶埠號,伺服器IP地址 和 伺服器埠號-》 可以唯一確                                                       定網際網路絡中 每個TCP連線中的雙方。

②.32位序號

標識:從TCP發端 向 TCP收端 傳送的 資料位元組流位置。表示在這個報文段中的第一個資料位元組。每一個位元組對應一個序號。範圍(0 ~ 2^32 -1)。(指的是當前報文段的一個位元組的序號。

 

序列號不會從0或1開始,而是建立連線時由計算機生成的一個隨機數作為其初始值,通過SYN包傳送給接收端主機。然後在將每轉發過去的位元組數累加到初始值上表示資料的位置。

③.32位確認號

期望收到下一個報文段的第一個位元組序列

比如:A傳送一個報文段序號為 501,資料長度為200,當B接收到501 - 700報文段。則希望下一次接受的資料序號為701.。

注意:①確認號 = N,表示到N-1為止的所有資料都正確收到。

④URG ...等

這裡寫圖片描述

這裡寫圖片描述

⑤16位視窗

佔兩個位元組。視窗值的範圍是【0,2^16 -1】之間的整數(65535)。

TCP提供一種流量控制機制。

視窗指的是:傳送本報文段的一方的接收視窗,(而不是自己的傳送視窗)。

視窗值:告訴對方-》從本報文段首部中的確認號算起,接收方目前允許對方傳送的資料量。之所以要有這個限制,是因為接收方的資料快取空間是有限的。總之,視窗值作為接受方讓傳送方設定其傳送視窗的依據。

⑥校驗和

佔兩個位元組。

校驗 覆蓋了整個TCP報文段:TCP首部 和 TCP資料。

這是一個強制性的欄位。一定是由發端計算和儲存;並由收端進行驗證。

在計算校驗和時:要在TCP報文段前面加上12個位元組的偽首部。

⑦4位的資料偏移 最大表示為 1 1 1 1(15)。其單位為4個位元組。也就是15*4 = 60
⑧16位的緊急指標

兩個位元組。緊急指標僅在URG = 1時才有意義。

他指出本報文段中的緊急資料的位元組數(緊急資料結束後就是普通資料)。因此緊急指標指出了緊急資料的末尾在報文段中的位置。當all緊急資料都處理完時,TCP就告訴應用程式恢復到正常操作。

值得注意的是:及時視窗為0時,也可以傳送緊急資料。

⑨保留位 設定為0

三次握手和四次揮手

  1.序列號seq

    佔四個位元組,用來標記資料段的順序,TCP把連線中傳送的所有資料位元組都編上了一個序號,第一個位元組的編號有本地隨機產生,給位元組編上序號之後,就給每一個報文段指派一個序號,序列號seq就是這個報文段中的第一個位元組的資料編號。

  2.確認號

    佔四個位元組,期待收到對方下一個報文段的第一個資料位元組的序號,序列號表示報文段攜帶資料的第一個位元組編號,而確認號指的是期望接收到下一個位元組的編號,因此報文段的最後一個位元組的編號+1就是確認號。

  3.確認ACK

    佔以為bit位,僅當ACK = 1,確認號欄位才有效。

  4.通步SYN

    連線建立時用於同步序號。當SYN = 1,ACK = 0表示:這是一個連線請求報文段。若同意連線,則在響應報文段中使用SYN = 1,ACK = 1。因此SYN = 1表示一個連線請求,或連線接收報文。SYN這個標誌位只有在YCP建立連線才會被設定為1,握手完成後SYN被設定為0

  5.終止FIN

    用來釋放一個TCP連線

對服務而言,剛開始他建立套接字,執行繫結,監聽函式之後處於Listen狀態,等待客戶端傳送請求,進行相應的響應。

三次握手過程分析:

①第一次握手

  建立連線時:客戶端傳送了SYN包到伺服器,其中包含客戶端的初始序號seq = x,並進入SYN_SENT狀態,等待伺服器確認。(SYN = 1 , ACK = 0.表示這是一個TCP連線請求資料報文;序號seq = x,表明傳輸資料時的第一個資料位元組的序號是x)。

②第二次握手

  伺服器接收到請求之後,必須確認客戶的資料包。同時位元組也傳送了一個SYN包,即SYN+ACK包,此時伺服器進入SYN_RECV狀態。(確認報文段:標識位SYN = 1,ACK = 1,並且含有伺服器的初始序號seq(伺服器)= y,以及伺服器對客戶端初始序號的確認號ack(伺服器)= seq(客戶端) + 1 = x +1)

③第三次握手

  客戶端接受到伺服器的SYN + ACK包,向伺服器傳送一個序列號(seq = x +1)確認號ack(客戶端)=y + 1,此包傳送完畢,客戶端和伺服器進入ESTAB_LISHED(TCP連線成功狀態)

常見的面試問題:

  1.為什麼需要三次握手,兩次可以嗎?或者四次,五次可以嗎?

    情況1.兩次握手:

    客戶端發出SYN,客戶端發出ACK。這樣會導致一種情況伺服器給客戶端回ACK確認報文段時,發生了資料丟失,那麼客戶端就會進行重傳。這樣會導致伺服器會產生多個無效連線,佔用資源,導致伺服器癱瘓--》“SYN的洪水攻擊”。

    由於網路問題,客戶端傳送的SYN都滯留在了中途,導致超時重傳。同樣伺服器端會接收到很多的SYN,導致很多的無效連線。

總結:第三次握手為了防止:如果客戶端遲遲沒有收到伺服器返回的確認報文,這時會放棄連線,重新啟動一條連線請求,但問題是伺服器不知道客戶端沒有收到,所以伺服器會收到多個連線,浪費連線開銷。

  情況2.四次握手:

    也就是將第二次握手的ACK和SYN分開發送,這樣一來會導致時間效率的降低,發了多個包資源,以及多於包占用了傳送和接受的緩衝區。

但是他可以成功的建立連線。

四次揮手過程分析(假設客戶端為關閉主動方)

①第一次揮手:

  首先,客戶端傳送一個FIN,請求關閉客戶端到伺服器的資料傳輸,然後等待伺服器的確認。其中終止標誌位FIN = 1,序列號seq = u。客戶端處於FIN_WAIT_1狀態。

②第二次揮手:

  伺服器收到這個FIN,他立即傳送一個ACK確認報文段,確認ack為收到序號加1,同時傳送一個自己的序號為seq = v.。伺服器進入CLOSE_WAIT狀態。

此時TCP伺服器程序進入就通知高層應用程序,因而從客戶端到伺服器的連線就釋放了。此時是“半關閉狀態”,即客戶端不可以傳送資料給伺服器,但伺服器可以傳送給客戶端。

③第三次揮手:

  此時如果伺服器沒有資料報傳送給客戶端,其應用程式就會通知TCP釋放連線,然後伺服器傳送一個FIN給客戶端,此時伺服器處於LAST_ACK狀態。

④第四次揮手

  客戶端收到FIN後,併發會了一個ACK確認報文段,此時伺服器直接close,而客戶端進入TIME_WAIT狀態,等待2MSL時間。再進入CLOSE狀態。

面試常問問題:

1.為什麼主動關閉方最後需要2MSL的時間

  首先,2MSL(Maximum Segment LifeTime),就是最大報文生存時間,是任何報文在網路中存在的最長時間,超過這個時間報文將被丟棄。RFC 793中規定MSL為2分鐘,實際應用中常用的是30秒,1分鐘,2分鐘等。

  等待2MSL的目的是:防止最後一個ACK包對方沒有收到。如果沒有等待時間,傳送完確認報文段就立即釋放連線的話,伺服器將無法重傳,因此也就收不到確認,就無法按步驟進入CLOSE狀態,即伺服器必須收到確認後,客戶端才能CLOSE。

TIME_WAIT狀態時兩端的埠都不能使用,要等2MSL時間結束才能繼續使用。當連線處於2MSL等待階段時任何遲到的報文段都將被丟棄。防止了已經失效的連線請求報文出現在連線中,在該時間內,產生的所有報文段就可以都從網路中消失。

2.為什麼是四次揮手,而不是三次或者五次,六次?

  雙方關閉連線,要經過雙方的同意。所以,首先是客戶端給伺服器傳送FIN,要求關閉連線,伺服器接收到會發送一個ACK進行確認。伺服器然後在傳送一個FIN,客戶端傳送ACK進行確認,並進入TIME_WAIT狀態,等待2MSL之後自動關閉。