1.四次揮手服務端和客戶端的狀態:
- 主動關閉連接的一方,調用 close ();協議層發送 FIN 包;
- 被動關閉的一方收到 FIN 包後,協議層回覆 ACK;然後被動關閉的一方,進入 CLOSE_WAIT 狀態,主動關閉的一方等待對方關閉,則進入 FIN_WAIT_2 狀態;此時,主動關閉的一方等待被動關閉一方的應用程序,調用 close 操作;
- 被動關閉的一方在完成所有數據發送後,調用 close () 操作;此時,協議層發送 FIN 包給主動關閉的一方,等待對方的 ACK,被動關閉的一方進入 LAST_ACK 狀態;
- 主動關閉的一方收到 FIN 包,協議層回覆 ACK;此時,主動關閉連接的一方,進入 TIME_WAIT 狀態;而被動關閉的一方,進入 CLOSED 狀態;
- 等待 2MSL 時間,主動關閉的一方,結束 TIME_WAIT,進入 CLOSED 狀態;
2.總結上面的過程,得出一次 socket 關閉操作:
- 主動關閉連接的一方 – 也就是主動調用 socket 的 close 操作的一方,最終會進入 TIME_WAIT 狀態;
- 被動關閉連接的一方,有一箇中間狀態,即 CLOSE_WAIT,因爲協議層在等待上層的應用程序,主動調用 close 操作後才主動關閉這條連接;
- TIME_WAIT 會默認等待 2MSL(2 倍的max segment lifetime) 時間後,才最終進入 CLOSED 狀態;
- 在一個連接沒有進入 CLOSED 狀態之前,這個連接是不能被重用的!
3.TIME_WAIT 並不可怕,CLOSE_WAIT 纔可怕,因爲 CLOSE_WAIT 很多,表示說:
- 要麼是你的應用程序寫的有問題,沒有合適的關閉 socket;
- 要麼是說,你的服務器 CPU 處理不過來(CPU 太忙)或者你的應用程序一直睡眠到其它地方 (鎖,或者文件 I/O 等等),你的應用程序獲得不到合適的調度時間,造成你的程序沒法真正的執行 close 操作。
4.TIME_WAIT 有什麼用?
- 防止前一個連接上延遲的數據包或者丟失重傳的數據包,被後面複用的連接錯誤的接收
- 確保連接方能在時間範圍內,關閉自己的連接
5.爲什麼 TIME_WAIT 狀態 停留 2MSL(max segment lifetime)時間?
-
爲了防止上次連接的報文數據影響到下次的連接,有充分的的時間處理上次連接的報文信息。
-
客戶端最後發的 ACK 可能會丟失,此時服務器端會重新發送 FIN,若此時客戶端處於 closed,會響應 rst (rst 段標識復位,用來異常的關閉連接) 而不是 ACK。因此客戶端是 TIME_WAIT 狀態,不是 closed。
6.什麼原因造成出現大量CLOSE_WAIT?
- 出現大量 close_wait 的現象主要原因是某種情況下對方關閉了 socket 鏈接,但是我方忙與讀或者寫,沒有關閉連接。
7.什麼原因造成大量 TIME_WAIT
- 在高併發短連接的 TCP 服務器上,當服務器處理完請求後立刻主動正常關閉連接。這個場景下會出現大量 socket 處於 TIME_WAIT 狀態。如果客戶端的併發量持續很高,此時部分客戶端就會顯示連接不上。
8.如何處理大量CLOSE_WAIT?
- 給每一個 socket 設置一個時間戳 last_update,每接收或者是發送成功數據,就用當前時間更新這個時間戳。定期檢查所有的時間戳,如果時間戳與當前時間差值超過一定的閾值,就關閉這個 socket。
- 使用一個 Heart-Beat 線程,定期向 socket 發送指定格式的心跳數據包,如果接收到對方的 RST 報文,說明對方已經關閉了 socket,那麼我們也關閉這個 socket。
【Java 面試那點事】
這裏致力於分享 Java 面試路上的各種知識,無論是技術還是經驗,你需要的這裏都有!
這裏可以讓你【快速瞭解 Java 相關知識】,並且【短時間在面試方面有跨越式提升】
面試路上,你不孤單!