- 問1: 請你說一下tcp的三次握手
- 一次握手
- 兩次握手
- 三次握手
- 問: 為什么不四(更多)次握手?
- 問 2: 請說一下 tcp 的 4 次揮手
- 一次揮手
- 兩次揮手
- 問題:能不能等到數據傳輸完成再返回 ack?
- 三次揮手
- 四次揮手
- 問: 為什么要等兩個最大報文存在時間?
bg: tcp 是可靠的連接,如何保證
- 建立連接: 三次握手
- 傳輸: 重傳,擁塞機制
- 斷開: 四次揮手
問1: 請你說一下tcp的三次握手
如果自己去設計一個tcp建立連接的流程會怎么做?
一次握手
客戶端(請求連接:SYN)->服務端
問題 1: 客戶端不知道服務端能不能收到
問題 2: 客戶端不知道服務端是否可以發送數據
問題 3: (假設服務端收到請求,并同意連接)服務端不知道客戶端是否可以接收到數據.
舉個例子:
客戶端連接的是一個關閉的服務器,如果只進行一次握手,客戶端發送給關閉的服務器,服務器是不可能收到的.
結論: 一次握手不行
兩次握手
客戶端(請求連接:SYN)->服務端
服務端(ack+SYN)->客戶端
問題 1: 服務端不知道客戶端是否可以收到數據
舉個例子:
第二次握手的數據丟包了,客戶端沒有收到
這時候客戶端認為連接沒有建立好(沒有收到服務器的返回)
服務器認為連接已經建立好了
這時服務器發送數據給客戶端,客戶端是不接收的(因為客戶端認為連接沒有建立好)
結論: 兩次握手也不行
三次握手
客戶端(請求連接:SYN)->服務端
服務端(ack+SYN)->客戶端
客戶端(ack)->服務端
服務端知道客戶端可以發送與接受數據
客戶端知道服務端可以發送與接受數據
結論: 三次握手可以
問: 為什么不四(更多)次握手?
三次握手已經滿足需求,多余的只是在浪費性能.
問 2: 請說一下 tcp 的 4 次揮手
自己來設計斷開連接的流程會怎么設計?
終端 A 數據傳輸完成,準備與終端 B 斷開連接
一次揮手
A(FIN)->B
問題 1:A不知道 B 是否能收到斷開連接的信號
問題 2: A不知道 B 的數據是否已經傳輸完成,可能會丟失數據
舉個例子:
B 并沒有傳輸完成數據,這時 A 斷開了連接,沒有完成傳輸的數據就丟失了
結論: 一次揮手不行
兩次揮手
A(FIN)->B
B(ack)->A
問題 1: A不知道 B 的數據是否已經傳輸完成,可能會丟失數據
問題:能不能等到數據傳輸完成再返回 ack?
不能
舉個例子: 如果 A 發送 FIN 給 B ,這個過程可能丟包了,B 沒有收到 A 發起的 FIN 就不會 ACK,所以 3 有重傳,只要一段時間沒有收到 ACK 就會重傳 FIN
那么問題來了,如果等到數據傳輸完成再返回 ack,那么如果 B 數據沒有傳輸完成,還需要傳輸很久,比如 10 分鐘,那么這十分鐘都沒有返回 ack,A 端沒收到 ack 會認為丟包了,就會不斷的重發 FIN
結論: 兩次揮手不行
三次揮手
A(FIN)->B
B(ack)->A
B(FIN)->A
問題: B 不知道 A 是否能收到發出的 FIN 信號,如果丟包,A 會保持 tcp 連接
四次揮手
A(FIN)->B
B(ack)->A
B(FIN)->A
A(ack)->B
保證雙方數據都傳輸完畢,等待兩個報文段最大存活時間就會斷開
問: 為什么要等兩個最大報文存在時間?
有兩種說法:
- 確保 B 能收到 ack,不然 B 就會認為FIN丟包了,繼續發送 FIN
- 最后 ack 后可能網絡中還有一些數據包(丟包重傳的),如果這時再建立連接可能會是同一個端口,那么這些(上一個連接)數據包可能在新的連接中被接受到,造成數據的錯亂.