TCP中shutdown函數/TCP套接字選項SO_LINGER來實現TCP優雅關閉

一 Shutdown函數

有時候,我們想給服務器發送一個FIN,告訴它們我們已經完成了數據發送,但是仍然保持套接字描述符打開以便讀取。

這時候就需要一種關閉TCP連接其中一半的方法。

確切地說,close() / closesocket() 用來關閉套接字,將套接字描述符(或句柄)從內存清除,之後再也不能使用該套接字,與C語言中的 fclose() 類似。應用程序關閉套接字後,與該套接字相關的連接和緩存也失去了意義,TCP協議會自動觸發關閉連接的操作。

shutdown() 用來關閉連接,而不是套接字,不管調用多少次 shutdown(),套接字依然存在,直到調用 close() / closesocket() 將套接字從內存清除。

調用 close()/closesocket() 關閉套接字時,或調用 shutdown() 關閉輸出流時,都會在發送緩衝區中的數據發送完畢後向對方發送 FIN 包。FIN 包表示數據傳輸完畢,計算機收到 FIN 包就知道不會再有數據傳送過來了。

 

Close函數的默認情況:

在套接字上不再發出發送或接收請求;套接字發送緩衝區中的內容被髮送到對端。

如果描述符引用計數變爲0,在發送完發送緩衝區中的數據後,跟以正常的TCP連接終止序列(發送FIN)。套接字接收緩衝區中的數據被丟棄。

Shutdown函數(SHUT_WR)

在套接字上不再發出發送請求;進程仍可從套接字接收數據;套接字發送緩衝區中的數據被髮送到對端,後跟以正常的TCP連接終止序列(發送FIN),對套接字接收緩衝區無任何影響。

 

shutdown(shut_wr)實現優雅關閉的點在(自己總結的):

(1)close會關閉套接字2個方向的連接,即使對方還有數據需要發送或即使接收緩衝區中有數據未被處理。

而shutdown只關閉一個方向的連接,客戶端還會收到對方發送的數據,接收緩衝區中的數據也會被處理。

(2)

close調用後通常立即返回(在發送完發送緩衝區的數據),很大可能在服務端讀套接字接收緩衝區中的剩餘數據前返回。對於服務器主機來說,服務器應用進程在讀這些剩餘數據之前就崩潰(會發送FIN)是完全可能的,而客戶端應用進程不會知道。

後跟一個read調用的shutdown一直等到接收到了對端的FIN才返回。保證對方應用進程已成功讀取接收緩衝區中的數據。且對方數據也發鬆完畢。

 

 

 

 

 

 

二 TCP套接字選項SO_LINGER

本選項指定close函數對面向連接的協議如何操作。

默認操作是close函數立即返回,如果有數據殘留在發送緩衝區,系統會試着把這些數據發送給對端。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章