文章目錄
- 三種方法效果的區別
- 套接字Socket關閉與釋放的區別
- 服務器執行三種關閉操作后,繼續發送/接收數據會發生什么
- `socket.shutdownOutput` 關閉連接
找了半個小時沒一個說明白的帖子,真的折磨
三種方法效果的區別
socket.close()
Socket主動禁止輸入和輸出流,關閉Socket并丟棄所有的緩沖區未發送數據,發送FIN四次分手,等待關閉連接,釋放Socket、輸入輸出流資源output/input.close()
只關閉本機上的輸入/輸出流,影響的是程序<--->接口
這一段。Socket不會禁止輸入/輸出流操作,它不知道自己的輸入/輸出流已經關閉了。這是程序內部問題,雙方Socket行為還是保持原樣,但是會因為到達的數據沒法交付給程序導致報錯甚至崩潰socket.shutdownOutput/Input()
Socket主動禁止輸入/輸出流,發送FIN四次分手,等待關閉連接,釋放Socket、輸入/輸出流等資源
綜上,socket.close()
方法關閉整個Socket連接,禁止輸入和輸出操作,并且最終關閉連接和釋放資源。output.close()
方法關閉輸出流,禁止進一步的寫操作,具體的影響取決于實現和是否與Socket關聯。socket.shutdownOutput()
方法關閉Socket的輸出流,禁止寫操作,但允許繼續使用輸入流,發送FIN包通知對方關閉連接,并以四次握手過程完成連接關閉。
套接字Socket關閉與釋放的區別
-
套接字的關閉(Socket Close):
關閉套接字是指在網絡通信結束或不再需要使用套接字時,顯式地關閉套接字連接。通過調用套接字對象的close()
方法,可以關閉套接字。關閉套接字后,不再能夠進行數據傳輸,連接也被終止。關閉套接字是網絡編程中常用的操作,用于釋放與遠程主機的連接以及清理資源。 -
套接字資源的釋放(Socket Resource Release):
套接字資源的釋放是指在關閉套接字后,操作系統或編程語言運行環境會自動回收與套接字相關的資源。這些資源包括分配給套接字的內存空間、操作系統中的套接字句柄、網絡協議棧中的緩沖區等。套接字資源的釋放由操作系統或運行環境負責處理,通常會在套接字關閉后的一段時間內完成。
總結來說,關閉套接字是由程序顯式調用的操作,用于結束連接并停止數據傳輸。而套接字資源的釋放是隨后由操作系統或運行環境自動進行的過程,用于回收之前使用的資源。關閉套接字是觸發套接字資源釋放的條件之一。
服務器執行三種關閉操作后,繼續發送/接收數據會發生什么
當服務器執行 socket.close()
、output.close()
或 socket.shutdownOutput()
操作后,如果客戶端試圖向服務器發送數據,將會發生以下情況:
-
服務器執行
socket.close()
后:- 服務器Socket被關閉,無法接收客戶端發送的數據。
- 客戶端的發送操作將失敗,并且可能引發異常(如連接錯誤或連接重置RST)。 在網絡層面,當客戶端嘗試發送數據時,其操作系統會報錯連接已關閉。
-
服務器執行
output.close()
后:- 客戶端可以成功發送數據到服務器,并且服務器仍然可以通過輸入流接收來自客戶端的數據。只是服務器無法通過輸出流向客戶端發送任何數據(報錯輸出流已釋放)。
-
服務器執行
socket.shutdownOutput()
后:- Socket的輸入端仍然是打開狀態,而輸出端被關閉。這意味著Socket可以繼續接收來自對方的數據,但無法再向對方發送數據。
-
服務器執行
input.close()
后:- 客戶端可以成功發送數據到服務器,但服務器沒法接收數據了,因為輸入流已經釋放掉了,數據會卡在Socket那步
-
服務器執行
socket.shutdownInput()
后:- 客戶端會收到服務器發來的FIN,就不會給服務器發數據了。如果非要發,就會引發異常和錯誤
socket.shutdownOutput
關閉連接
此種TCP四次分手過程:
- 服務器
socket.shutdownOutput
向客戶端發送第一個FIN,并關閉輸出流。 - 客戶端接收到服務器的FIN后,發送一個ACK確認收到,并進入TIME_WAIT狀態。
- 客戶端發送第二個FIN,并關閉輸出流。
- 服務器接收到客戶端的FIN后,發送一個ACK確認收到,并關閉Socket。
- 客戶端在收到服務器的ACK后,會等待一段時間(2MSL),確保服務器收到了自己剛剛發的正確地ACK并關閉Socket。這段時間被稱為2MSL(兩倍最大報文生存時間)
ps.在TCP協議中,FIN和ACK報文是用來控制連接狀態的特殊報文,它們不受Socket輸出流的影響。當服務器調用 socket.shutdownOutput() 方法后,它會關閉自己的輸出流,但仍然可以發送ACK報文來響應客戶端的FIN報文。