文章目錄
- 昨日內容復習
- TCP 的四次揮手?
- TCP 為什么要四次揮手?
- 在客戶端處于 FIN_WAIT_2 狀態時,如果此時收到了亂序的來自服務端的 FIN 報文,客戶端會如何處理?何時進入 TIME_WAIT 狀態?
- TCP 四次揮手丟了怎么辦?
- TCP 的延遲應答和累積應答?
- TCP 會出現三次揮手嗎?
- TCP 的 MSL?
- 復習計算機網絡 Day3:TCP 協議的其他相關問題
- 已經建立了 TCP 連接,客戶端突然出現故障了怎么辦?
- 什么時候用長連接,什么時候用短連接?
- TCP 的半連接隊列和全連接隊列?
- 什么是 SYN 攻擊?如何避免?
- TIME_WAIT 的作用?過多如何解決?
- TIME_WAIT 為什么要經過 2MSL?
- CLOSED_WAIT 過多如何解決?
昨日內容復習
TCP 的四次揮手?
TCP 的四次揮手過程可以總結如下,為了方便描述,我們將客戶端認定為主動關閉方,將服務端認定為被動關閉方:
- 第一次揮手:客戶端發送 FIN 置位的報文到服務端,并從 ESTABLISED 狀態進入 FIN_WAIT_1 狀態,此時客戶端為半關閉狀態,客戶端仍然可以接收數據,但是不會再發送數據;
- 第二次揮手:服務端接收到客戶端的 FIN 報文后,發送 ACK 報文對 FIN 報文進行確認,同時進入 CLOSED_WAIT 狀態,再次期間服務端將繼續處理應用層還沒有發送完的數據。客戶端收到 ACK 后進入 FIN_WAIT_2 狀態;
- 第三次揮手:服務端處理好數據后,發送 FIN 報文,隨后進入 LAST_ACK 狀態;
- 第四次揮手:客戶端接收到來自服務端的 FIN 報文后,進入 TIME_WAIT 狀態,等待 2MSL 時間后客戶端關閉。服務端收到 ACK 報文后立即關閉。
TCP 為什么要四次揮手?
TCP 進行四次揮手而不是三次揮手的原因是服務端可能在收到客戶端的 FIN 后仍然有數據要發送,因此服務端確認客戶端發來的 FIN 報文的 ACK 報文與服務端發送給客戶端的 FIN 報文在有數據沒有處理完的情況下不能合并,因此 TCP 需要四次揮手。
當然,需要注意的是,TCP 可以三次揮手,當服務端沒有數據發送給客戶端時,服務端將 ACK 與 FIN 合并,發送 FIN-ACK 報文。
在客戶端處于 FIN_WAIT_2 狀態時,如果此時收到了亂序的來自服務端的 FIN 報文,客戶端會如何處理?何時進入 TIME_WAIT 狀態?
如果客戶端收到了亂序的來自服務端的 FIN 報文,會將其存入緩沖區,等待服務端的其他數據到達,一并放入緩沖區。當客戶端接收不到數據時,按順序比對報文的序列號,如果 FIN 報文的序列號順序且合法,則將其視為正確的 FIN 報文,回發 ACK 報文并進入 TIME_WAIT 狀態;否則丟棄 FIN 報文,等待正確的 FIN 報文。
TCP 四次揮手丟了怎么辦?
- 第一次揮手丟失:客戶端發送給服務端的 FIN 報文丟失,此時客戶端收不到來自服務端的 ACK 報文,觸發超時重傳;
- 第二次揮手丟失:服務端確認客戶端的 FIN 報文的 ACK 報文丟失,此時客戶端會認為自己的 FIN 報文丟失,客戶端觸發超時重傳;
- 第三次揮手丟失:客戶端沒有收到服務端的 FIN 報文,此時客戶端處于 FIN_WAIT_2 狀態,不會給服務端發送 ACK 報文,因此服務端會觸發超時重傳,重新發送 FIN 報文;
- 第四次揮手丟失:服務端沒有收到客戶端的 ACK 報文,此時服務端會重新發送 FIN 報文給客戶端。客戶端發送 ACK 之后進入 2MSL 的 TIME_WAIT 狀態,當再次收到 FIN 報文后,會重置 2MSL 計時器,并再次發送 ACK 報文。如果客戶端此時已經到達 2MSL 并關閉,那么服務端會在超時重傳最大次數上限后關閉連接。
TCP 的延遲應答和累積應答?
- 延遲應答:TCP 不會立即發送 ACK 應答接收到的報文,而是積累一定的數據后,與 ACK 報文一并發送;
- 累積應答:TCP 頭部當中的確認號表示的是發送報文的一方期望下一次收到的序列號,說明該序列號之前的字節已經全部收到,這就是累積應答。
TCP 會出現三次揮手嗎?
會,當被動關閉方收到主動關閉方 FIN 報文后,沒有數據要發送時,將 ACK 和 FIN 合并發送,此時就出現了三次揮手。
TCP 的 MSL?
指的是報文的最長生命周期,即報文在網絡中被丟棄之前的最長生存時間。TCP 報文被包裹在 IP 數據報中,IP 數據報的報頭有 TTL 字段。
復習計算機網絡 Day3:TCP 協議的其他相關問題
已經建立了 TCP 連接,客戶端突然出現故障了怎么辦?
TCP 存在保活計時器,如果客戶端發生故障,服務端不會一直等待。計時器通常設置為兩個小時,每當客戶端有消息發送過來,服務端都會重置計時器。超時之后,服務端每隔一定的時間周期(75 s)向客戶端發送探測報文,如果連續十次都沒有回復,服務端會認為客戶端發生故障,斷開連接。
什么時候用長連接,什么時候用短連接?
長連接多用于操作頻繁的點對點通訊,而且連接數不能太多。例如,數據庫的連接就是長連接。
Web 網站的 HTTP 服務一般使用短連接,短連接可以快速釋放資源。
TCP 的半連接隊列和全連接隊列?
半連接隊列:也稱 SYN 隊列。服務端收到客戶端的 SYN 請求連接報文后,內核會把該連接存儲到半連接隊列中,并向客戶端發送 SYN-ACK 報文。換句話說,半連接隊列(SYN 隊列)存儲的就是已經向服務端發起了連接請求但是還沒有完成連接建立的客戶端。
全連接隊列:也稱 ACCEPT 隊列。服務端收到第三次握手客戶端發送的 ACK 報文后,內核就會把該客戶端從 SYN 隊列中移除,并轉入到 ACCEPT 隊列。
什么是 SYN 攻擊?如何避免?
SYN 攻擊指的是惡意攻擊方通過合法手段不斷向服務端發送 SYN 報文,從而使得合法用戶無法得到服務響應。當大量的 SYN 請求到來時,服務端會進入 SYN_RECV 狀態,將連接加入到 SYN 隊列并分配進程控制塊,同時回發 SYN-ACK 報文,當服務端等不到 ACK 報文時,還會不斷觸發超時重傳重新發送 SYN-ACK 報文,最終導致服務端資源耗盡。
解決辦法:
- Cache:收到 SYN 報文后使用 Hash 表保存 SYN 報文的信息,發送 SYN-ACK 后,收到 ACK 才為該連接分配 TCB,節省資源;
- Cookie:服務端收到 SYN 報文后,不直接分配資源,而是通過加密算法生成一個 SYN Cookie 作為初始序列號。只有收到客戶端發送的合法的 ACK 后才分配連接資源。
- Proxy 防火墻:設立中間層防火墻,確認連接有效后,才向內部服務器發送 SYN 請求。
- 減少 SYN-ACK 重傳次數;
- 監視半連接隊列和全連接隊列當中的無效連接;
- 增大半連接隊列的數量;
TIME_WAIT 的作用?過多如何解決?
TCP 常用的三種狀態:ESTABLISHED 表示連接建立,CLOSED_WAIT 表示被動關閉,TIME_WAIT 表示主動關閉。
TIME_WAIT 的作用
- 確保主動關閉方發送的最后一個 ACK 到達被動關閉方:主動關閉方在接收到 FIN 報文后,發送 ACK 予以確認,并進入 2MSL 的 TIME_WAIT 狀態。如果這個 ACK 丟失,那么被動關閉方會重發 FIN,主動關閉方收到后會重發 ACK。如果沒有 TIME_WAIT,那么被動關閉方在沒有收到 ACK 之后,會不斷觸發超時重傳重新發送 FIN 報文,導致資源的消耗。
- 避免舊連接的延遲報文干擾新的連接:TCP 連接通過四元組唯一標識。如果舊的連接中存在由于網絡阻塞而沒有到達對端的報文,則接收方會誤認為這些報文是新的連接發送的,導致數據錯亂。舊的連接等待 2MSL 再關閉可以確保舊的報文在網絡中全部消亡;
- 確保全雙工通道的可靠關閉:TCP 是全雙工協議,雙方都需要關閉自己的連接。TIME_WAIT 可以確保雙方都能完成關閉流程,即使主動關閉方發送給被動關閉方的 ACK 丟失,由于主動方處于 TIME_WAIT,仍然可以接收 FIN 并重發 ACK。
TIME_WAIT 的副作用
過多的 TIME_WAIT 會占用端口和內存資源(高并發短連接場景下),導致新的連接無法建立。
解決辦法:
- 快速回收 TIME_WAIT;
- 調整 MSL 時間;
- 負載均衡或連接池:復用長連接以減少短連接數量。
TIME_WAIT 為什么要經過 2MSL?
第一個 MSL:確保主動關閉方的 ACK 到達對端;
第二個 MSL:確保對端重傳的 FIN 可以到達本端;
CLOSED_WAIT 過多如何解決?
CLOSED_WAIT 過多代表被動關閉方為能正確地關閉連接,導致連接資源長期占用。可能是由于程序 Bug 及配置問題導致的,應該去檢查程序。