java網路篇-tcp的握手和揮手!
1. tcp 的報文
1.1 概念
tcp 報文是 tcp 協議傳輸的資料單元,也叫作報文段
1.2 報文格式圖

1.3 報文格式分析


2. 三次握手
2.1 概念
所謂三次握手 (Three-Way Handshake) 即建立 tcp 連線,就是指建立一個 tcp 連線時,需要客戶端和服務端總共傳送3個包以確認連線的建立。在socket 程式設計中,這一過程由客戶端執行 connect 來觸發。
2.2 流程圖

第一次握手:
Client 將標誌位 SYN 置為1,隨機產生一個值 Seq=X,並將該資料包傳送給 Server,Client 進入 SYN_SENT 狀態,等待 Server 確認。
第二次握手:
Server 收到資料包後由標誌位 SYN=1 知道 Client 請求建立連線,Server 將標誌位 SYN 和 ACK 都置為1,Ack=X+1,隨機產生一個值Seq=Y,並將該資料包傳送給 Client 以確認連線請求,Server 進入 SYN_RCVD 狀態。
第三次握手:
Client 收到確認後,檢查 Ack 是否為 X+1,ACK 是否為1,如果正確則將標誌位 ACK 置為1,Ack=Y+1,並將該資料包傳送給 Server,Server 檢查 Ack 是否為 Y+1,ACK是否為1,如果正確則連線建立成功,Client 和 Server 進入 ESTABLISHED 狀態,完成三次握手,隨後 Client 與 Server 之間可以開始傳輸資料了。
3. 四次揮手
3.1 概念
四次揮手 (Four-Way Wavehand) 即終止 tcp 連線,就是指斷開一個 tcp 連線時,需要客戶端和服務端總共傳送4個包以確認連線的斷開。在 socket 程式設計中,這一過程由客戶端或服務端任一方執行 close 來觸發。
由於 tcp 連線是全雙工的,因此每個方向都必須要單獨進行關閉,這一原則是當一方完成資料傳送任務後,傳送一個 FIN 來終止這一方向的連線,收到一個 FIN 只是意味著這一方向上沒有資料流動了,即不會再收到資料了,但是在這個 tcp 連線上仍然能夠傳送資料,直到這一方向也傳送了 FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。
3.2 流程圖

第一次揮手:
Client 傳送一個 FIN,用來關閉 Client 到 Server 的資料傳送,Client 進入 FIN_WAIT_1 狀態。
第二次揮手:
Server 收到 FIN 後,傳送一個 ACK 給 Client,確認序號為收到序號+1 (與 SYN 相同,一個 FIN 佔用一個序號),Server 進入CLOSE_WAIT 狀態。
第三次揮手:
Server 傳送一個 FIN,用來關閉 Server 到 Client 的資料傳送,Server 進入 LAST_ACK狀態。
第四次揮手:
Client 收到 FIN 後,Client 進入 TIME_WAIT 狀態,接著傳送一個 ACK 給 Server,確認序號為收到序號+1,Server 進入 CLOSED狀態,完成四次揮手。
4. 為什麼握手是三次
首先,我們要知道 tcp 是全雙工的,即客戶端在給伺服器端傳送資訊的同時,伺服器端也可以給客戶端傳送資訊。而半雙工的意思是 A 可以給 B 發,B 也可以給 A 發,但是 A 在給 B 發的時候,B 不能給 A 發,即不同時,為半雙工。 單工為只能 A 給 B 發,B 不能給 A 發; 或者是隻能 B 給 A 發,不能 A 給 B 發。
我們假設 A 和 B 是通訊的雙方。我理解的握手實際上就是通訊,發一次資訊就是進行一次握手。
第一次握手: A 給 B 打電話說,你可以聽到我說話嗎?
第二次握手: B 收到了 A 的資訊,然後對 A 說: 我可以聽得到你說話啊,你能聽得到我說話嗎?
第三次握手: A 收到了 B 的資訊,然後說可以的,我要給你發信息啦!
在三次握手之後,A 和 B 都能確定這麼一件事: 我說的話,你能聽到; 你說的話,我也能聽到,這樣就可以開始正常通訊了。
如果兩次,那麼 B 無法確定 B 的資訊 A 是否能收到,所以如果 B 先說話,可能後面的 A 都收不到,會出現問題 。如果四次,那麼就造成了浪費,因為在三次結束之後,就已經可以保證 A 可以給 B 發信息,A 可以收到 B 的資訊; B 可以給 A 發信息,B 可以收到 A 的資訊。
5. 為什麼揮手是四次
A:"喂,先這樣,不說了 (FIN)。" A -> FIN_WAIT1
B: "我知道了 (ACK)。稍等,我還有話說 (傳輸資料)。" B-> CLOSE_WAIT | A-> FIN_WAIT2
B: "好了,我說完了,我也沒什麼可說了 (FIN)。" B -> LAST_ACK
A: "我知道了(ACK)。" A -> TIME_WAIT | B -> CLOSED
A 等待 2MSL,保證 B 收到了訊息,否則重說一次"我知道了",A -> CLOSED
這樣,通過四次揮手,可以把該說的話都說完,並且 A 和 B 都知道自己沒話說了,對方也沒話說了,然後就掛掉電話(斷開連結)了。
為了讓學習變得輕鬆、高效,今天給大家免費分享一套Java教學資源。幫助大家在成為Java架構師的道路上披荊斬棘。需要資料的歡迎加入學習交流群:9285,05736
