三次握手、四次揮手

**

什麼是三次握手

**

在網絡數據傳輸中,傳輸層協議TCP(傳輸控制協議)是建立連接的可靠傳輸,TCP建立連接的過程,我們稱爲三次握手。

第一次,客戶端向服務器發送SYN同步報文段,請求建立連接

第二次,服務器確認收到客戶端的連接請求,並向客戶端發送SYN同步報文,表示要向客戶端建立連接

第三次,客戶端收到服務器端的確認請求後,處於建立連接狀態,向服務器發送確認報文

客戶端是在收到確認請求後,先建立連接

服務器是在收到最後客戶端的確認後,建立連接

發起連接請求的一定是客戶端

**

爲什麼建立連接時要進行三次握手?

**

我們可以分析一次握手肯定是不行的,這樣服務器都不一定能收到連接請求

**

那麼如果是兩次握手呢?

**

如果是兩次握手,連接過程應該是這樣的,當服務器收到對端的連接請求時,就認爲連接建立好了,進入ESTABLISHED狀態。客戶端在收到服務器發來的同步確認報文後,就認爲連接建立好了,進入ESTABLISHED,在報文都能正常收到的情況下,兩次握手是可以安全建立連接的。

但是存在這樣的情況,假設第二次握手的報文丟失了,當前的狀態是,服務器認爲連接已經建立好了,可是客戶端沒有收到同步確認報文,認爲連接還沒有建立好,此時,服務器端的連接其實是無效連接,客戶端因爲沒有收到確認,便會向服務器重傳同步報文,同樣,在服務器收到客戶端的同步報文時,認爲連接已經建立好了,同樣糟糕的事情發生了,服務器給客戶端發送的同步確認報文丟失了,或者是說有人惡意向服務器不斷髮送SYN同步報文(SYN洪水)。那麼服務器端就會有大量的無效連接,服務器處理連接的數量是有限的,當有大量的無效連接建立後,服務器處理有效連接是能力就會受限,且建立連接會消耗大量是資源,至此有可能導致服務器崩潰。

這樣看來兩次握手是不可行的。

**

三次握手爲什麼是可行的呢?

**

在上面的兩次握手的方案中,我們看到建立連接過程中,是服務器先處於連接建立好的狀態,出現差錯時,客戶端沒有連接建立成功,致使服務器可能有大量的無效連接,導致服務器安全問題。

那麼在三次握手方案中,客戶端收到服務器的同步確認報文後,就認爲連接建立好了(先處於連接建立好的狀態),而服務器是要收到客戶端的確認報文後才認爲連接建立好了。

那麼也可能存在這樣的問題,在最後一次握手時,服務器沒有收到客戶端的確認報文,此時的狀態是,客戶端處於建立連接狀態,服務器處於沒有建立連接狀態,此時客戶端負責維護這次連接

三次握手中,是誰先發起請求,誰來負責維護這次連接,那麼會出現上面類似SYN洪水的問題嗎?顯然是不會的,自己發出SYN,最終無效連接還是建立在自己這方,客戶端也不會這麼無聊吧

而當客戶端嘗試向服務器發送數據時,服務器看到的是,還沒有建立連接的數據,服務器會響應一個帶有RST標誌位的報文,告知客戶端你需要先建立連接,此時當客戶端收到這個報文時,就會重新發起建立連接的請求。

總結下來就是,三次握手中,即使建立連接失敗,對服務器是沒有影響的,保證服務器的安全,而對客戶端而言,也不過是多次建立連接而已。並且在經過驗證,三次握手的成功率也是非常高的。

**

四次握手可行嗎?

**

很明顯,三次握手已經可以滿足我們的需求了,也就沒必要多一次而浪費資源了。

在兩次握手和三次握手的方案中,我們發現要保證客戶端先建立連接的話,能保證連接的安全建立。若是偶數次握手,或者是說讓服務器先建立連接,就是不安全不可行的方案。所以四次 握手是不可行的。

**

什麼是四次揮手

**

在網絡數據傳輸中,傳輸層協議斷開連接的過程我們稱爲四次揮手

第一次,A端像B端發送FIN結束報文段,準備關閉連接

第二次,B端確認A端的FIN,表示自己已經收到對方關閉連接的請求

中間這段時間,A端停止向B端發送數據,但是B端可以向A端發送數據,要將自己未處理完任務處理完

第三次,B端向A端發送FIN結束報文段,準備關閉連接

第四次,A端確認B端的FIN,進入TIME_WAIT狀態,此時A端進程已經退出,但是連接還在

當B端收到A端的ACK之後,先斷開連接

當A端等待2 MSL之後,確認的B端接收到ACK後,再斷開連接

發起斷開連接請求的一端最後要進入有一個TIME_WAIT狀態

發起連接請求的可以是客戶端也可以是服務器端

**

爲什麼斷開連接要四次?

**

不像建立連接的過程,服務器端在調用了accept()之後,剩下的都交給內核來處理,用戶空間不用做什麼,斷開連接是,A端調用close()關閉文件描述符後,A端就停止發送數據了進行發送,B端收到後結束報文段之後,的得知A端要斷開連接了,但是B端可能有自己還沒有處理完的數據,不能立即斷開連接,就要先給出回覆,表示自己已經收到消息了,然後將自己的數據處理完之後,可以斷開連接的時候,再調用close()發出斷開連接請求,在收到A端的確認回覆之後,斷開連接,這樣看來每一步都不能少,但是有時候若服務器端沒有什麼要處理的數據,就看可以直接調用close()捎帶上響應報文,此時就是3次

**

爲什麼先發起斷開連接請求的一端最後要等待 2MSL?

**

MSL爲一段報文從一段到一段的最大時間,也稱爲報文的最大生存時間,我們假設在上面的四次揮手過程中最後A端在收到B端的FIN之後,就關閉連接,最後B端在收到A端的確認報文之後也斷開連接,這種情況是我們預期的

試想是否存在這樣的情況,在A端已經關閉連接後,但是發給B端的ACK報文中途丟失,此時B端就會重發FIN結束報文段,但是A端已經關閉與這臺服務器的連接,並且已經開始了一段新的連接,那麼A端收到這個過期的FIN,誤認爲是關閉當前連接,給出錯誤處理。

也就是說A端等待 2MSL就 可以保證在B端沒有收到A 到ACK時,B端重發的FIN,A端來的及處理,然後重新確認等待2 MSL,保證了最後的ACK 報文 B端成功收到。

發佈了6 篇原創文章 · 獲贊 5 · 訪問量 172
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章