TCP協議中的SO LINGER選項

2021-09-24 10:34:01 字數 1219 閱讀 8717

so_linger選項用來設定延遲關閉的時間,等待套接字傳送緩衝區中的資料傳送完成。沒有設定該選項時,在呼叫close()後,在傳送完fin後會立即進行一些清理工作並返回。如果設定了so_linger選項,並且等待時間為正值,則在清理之前會等待一段時間。

以呼叫close()主動關閉為例,在傳送完fin包後,會進入fin_wait_1狀態。如果沒有延遲關閉(即設定so_linger選項),在呼叫tcp_send_fin()傳送fin後會立即呼叫sock_orphan()將sock結構從程序上下文中分離。分離後,使用者層程序不會再接收到套接字的讀寫事件,也不知道套接字傳送緩衝區中的資料是否被對端接收。如果設定了so_linger選項,並且等待時間為大於0的值,會等待套接字的狀態從fin_wait_1遷移到fin_wait_2狀態。我們知道套接字進入fin_wait_2狀態是在傳送的fin包被確認後,而fin包肯定是在傳送緩衝區中的最後乙個位元組,所以fin包的確認就表明傳送緩衝區中的資料已經全部被接收。當然,如果等待超過so_linger選項設定的時間後,還是沒有收到fin的確認,則繼續進行正常的清理工作,linux下也沒有返回錯誤。從這裡看來,so_linger選項的作用是等待傳送緩衝區中的資料傳送完成,但是並不保證傳送緩衝區中的資料一定被對端接收(對端宕機或線路問題),只是說會等待一段時間讓這個過程完成。如果在等待的這段時間裡接收到了帶資料的包,還是會給對端傳送rst包,並且會reset掉套接字,因為此時已經關閉了接收通道。

在使用這個選項來延遲關閉連線的時候有兩個地方需要注意:

1. 程序會睡眠,直到狀態不為fin_wait_1、closing、last_ack(也就是接收到對fin的ack包),或者等待超時

2. 在等待的過程中如果接收到帶資料的包還是會傳送rst包

3.消耗更多的額外資源

tcp協議是乙個通用的傳輸層協議,不關心上層具體的業務,如果要延遲關閉連線,最好是結合自己的業務和場景自己來管理,不要依賴這個選項。nginx的延遲關閉就是自己來管理的,覺得要比直接使用so_linger選項好一些,並且不會導致程序阻塞。 ngxin在傳送錯誤資訊後,會等待一段時間,讓使用者把所有的資料都傳送完。超過等待時間後,會直接關閉連線。通過lingering_close,nginx可以保持更好的客戶端相容性,避免客戶端被reset掉。

so_linger還有乙個作用就是用來減少time_wait套接字的數量。在設定so_linger選項時,指定等待時間為0,此時呼叫主動關閉時不會傳送fin來結束連線,而是直接將連線設定為close狀態,清除套接字中的傳送和接收緩衝區,直接對對端傳送rst包。

慎用TCP的選項SO LINGER

最近有一次效能測試,通訊程式出現錯誤,表現為伺服器處理速度明顯降低,檢查發現伺服器的很多控制代碼出於 time wait 狀態,justin 這個流氓的自己承認測試用例寫的有問題,在 recv 函式返回 0 後,沒有 close 控制代碼。我很鬱悶 google 了一下如何處理這類錯誤,發現了 so...

慎用TCP的選項SO LINGER

最近有一次效能測試,通訊程式出現錯誤,表現為伺服器處理速度明顯降低,檢查發現伺服器的很多控制代碼出於time wait狀態,justin這個流氓的自己承認測試用例寫的有問題,在recv函式返回0後,沒有close控制代碼。我很鬱悶google了一下如何處理這類錯誤,發現了so linger這個選項,...

TCP協議中FLAG的含義

tcp flag 標記 基於標記的tcp包匹配經常被用於過濾試圖開啟新連線的tcp資料報。示例 乙個虛擬連線的建立是通過三次握手來實現的 1.b syn a 假如有伺服器a 客戶機b.當b要和a通訊時,b首先向a發乙個syn synchronize 標記的包,告訴a請求建立連線.注意 乙個 syn包...