通過一些問題來討論 TCP 協議中的三次握手機制
- 說一下三次握手的大致過程?
- 為什么需要三次握手?2 次不可以嗎?
- 第三次握手,可以攜帶數據嗎?第二次呢?
- 三次握手連接階段,最后一次ACK包丟失,會發生什么?
1. 說一下三次握手的大致過程
客戶端在與服務器建立 TCP 連接時首先會進行三次握手。
第一次握手:客戶端給服務端發送一個 SYN 報文,并指明客戶端的初始化序列號 ISN,此時客戶端處于 SYN_SEND 狀態
第二次握手:服務器收到客戶端的 SYN 報文后,會以自己的 SYN 報文作為應答,同時也指定了自己的 ISN,并把客戶端發來的 ISN + 1 作為 ACK 的值,表示自己已經收到了客戶端的 SYN,此時服務器處于 SYN_RCVD 狀態
第三次握手:客戶端收到 SYN 報文后,會將服務器發來的 ISN + 1 作為 ACK 報文發出,表示已經收到了服務端的 SYN 報文,此時客戶端處于 ESTABLISHED 狀態?
最后服務器收到 ACK 報文之后,也會處于 ESTABLISHED 狀態,到這里,雙方的連接就建立好了
第一次客戶端發送 SYN 包,證明自身發送能力正常
第二次服務端發送?SYN + ACK 包,證明自身發送能力和接受能力正常
第三次客戶端發送 ACK 包,證明自身接受能力正常
2.?為什么需要三次握手?2 次不可以嗎?
為什么 2次不可以,主要原因就是不可靠
第一是可能會有已經失效的連接請求報文傳送到服務端,引起連接錯誤
因為路徑堵塞或者其他原因,客戶端發送的請求報文可能要很久才能到服務端。在一定時間內,如果客戶端沒有收到來自服務端的回應報文,就會重新發送一份請求報文。這次報文很順利地到達服務端,不過緊接著,第一次發送的請求報文也來到了服務端,這個請求報文已經失效了。如果是二次握手建立連接的話,服務端接收到這個失效的請求報文后,就會建立連接,從而導致錯誤。
第二是服務端在正確收到客戶端的請求報文后,不能確定自己給客戶端發送的響應報文,對方是否收到(如網絡丟包)
導致服務端在等著客戶端發送數據,而客戶端等著服務端返回響應
那 4 次握手行嗎?
可以但沒必要,三次握手已經確認了建立連接需要的信息了,第四次握手不會帶來新的信息,只能使得這個過程更加冗余。
3.?第三次握手,可以攜帶數據嗎?第二次呢?
這個問題 RFC 文檔中提到過,第三次握手時,客戶端向服務端返回的報文中可以攜帶數據,即使此時服務端是 SYN_REVEIVED 狀態,但由于數據報中也帶有 ACK 的值,服務端接受之后會先確定這個 ACK,然后建立連接,進入 ESTABLISHED 狀態,之后就能正常接受這個數據包了
但需要多注意的是,一般情況下第三次握手的報文中是不會攜帶數據的,大多數情況都是客戶端在發生第三次握手的報文之后,不等服務端先接受,就接著發送正常通信的數據包。服務端先接受到第三次握手包之后建立連接,接著正常接受數據包。但假如由于網絡原因,客戶端發送的第三次握手包丟失了,但接著發送的數據包正常被服務端接收,由于這個數據包也帶有 ACK 的值,服務端就會把這個數據包當作第三次握手包,先建立連接再正常讀取數據。至于真正的第三次握手包,如果是丟失了的話就丟失吧,沒影響。如果由于網絡原因而比數據包后到達,服務端會直接忽略
TCP 的第一二次握手,都是不可以攜帶數據的。第一次握手不能的原因是防止惡意的握手請求。第二次不能是因為此時服務端只確認了客戶端的 “發生能力正常”,卻不知道接受能力是否正常,所以還不能攜帶數據
4.?三次握手連接階段,最后一次ACK包丟失,會發生什么?
這個需要分情況看,第三次握手的 ACK 包丟失后,客戶端有沒有繼續發送帶有 ACK 的數據包,如果有,還是可以建立連接的。
如果沒有,也就是服務端此時遲遲接收不到來自客戶端的 ACK,那么站在服務端的視角,有可能是第二次握手時給客戶端的 SYN + ACK 包丟失,也有可能是客戶端第三次握手的 ACK 包丟失。不管哪種情況,服務端此時只需重新進行第二次握手。也就是發送客戶端一份新的 SYN + ACK 包即可,客戶端收到后也會重新發送一份 ACK 報文,建立連接
誠懇歡迎大家提出意見
......(未完待續