伺服器TCP網路程式設計實踐

2021-05-23 15:51:51 字數 2129 閱讀 1868

這個問題涉及到2個tcp連線狀態,close_wait與time_wait。我想描述清楚這2個狀態,將會對伺服器關閉的生命週期了解的更為清晰。

(1)定義

假設有伺服器a正在執行,接受從客戶端c傳送過來的連線。

在某個時間點上,c正常關閉了連線(一般正常關閉是使用close函式),此時伺服器在recv函式上會接收到乙個長度為0的訊息,表示對端(c客戶端)已經關閉了傳送連線,意味著c不會再向a傳送有意義的資料了,此時可能a還有部分資料沒有傳送給c(對於構建自己的網路庫的時候,可能在應用層上有各種自定義的網路緩衝,其中在這裡需要判斷所有的傳送緩衝是否都傳送完畢,或者網路庫定義的discard欄位開啟),所以a仍舊可以繼續向c傳送剩餘的資料,在所有資料傳送完畢後,再呼叫close函式,關閉socket連線,那麼從接收到0長度的對端關閉資訊到呼叫close關閉socket的這段時間,tcp狀態稱為close_wait。同時,再呼叫close函式解除close_wait狀態後,進入到last_ack狀態,需要等待對端c回答這個關閉。對端c接收到了乙個close()訊號上帶的syn,需要返回乙個ack,回答剛才說的last_ack的等待。請在這裡停一下。

此時大家可以想一下,首先a關閉通知c,進入到last_ack狀態,他在等待什麼?等待c告訴他,c收到通知將會關閉所有與a的連線。同時,c收到a的close之後,開發送這個回答,那麼誰又來告訴他這個回答已經到c了呢?他是否也需要再等待c的回答,回答告訴他他的回答已經收到,於是就沒完沒了了,因為永遠無法最後讓他們同時確定對方已經收到這個資訊(有點類似拜占庭將軍問題)。於是我們回過頭來,在理順思路,在a呼叫close,到達last_ack狀態之後,c會收到這個通知,他必須在關閉自己的所有與a的連線的之後,再次通知a他的關閉結束了,此時他傳送了乙個ack,進入到了我們所說的time_wait狀態,他期待這個ack會到達a,讓a從last_ack狀態到達真正的closed狀態。但是他不再期待a會沒完沒了的繼續回答這個ack了。於是他根據乙個基礎,從c到a的所有ip包,生命週期是msl,比如30秒,那麼從他這兒進入到time_wait狀態到最後c的last-ack狀態說他沒收到你的ack,最多隻可能有2個msl的時間,也就是1分鐘。

(2)影響

通過以上的分析,我們最後一定要總結出一句話來:「主動關閉的一方進入到time_wait狀態!」。如果記住這一句話,基本上就可以分清楚tcp狀態的終極奧義了。大家一定想知道,tcp這些狀態,我們到底應該如何把握,讓伺服器先關閉還是後關閉比較好呢?下面我們再仔細分析,先後關閉伺服器的優劣。

【原因1】首先,time_wait是不可避免的,這一句話,相信通過小結(1)的分析,已經確定了,根據unp的描述,這個時間大致是1到4分鐘。並且他是根據ip+port的對兒來確定的,假設伺服器a先關閉,那麼c對a的連線,再不設定別的引數的情形下,c會使用另外乙個埠與伺服器a進行連線,我們使用 netstat -anp | grep 伺服器端口號 可以看到c連線的埠號+1,而之前的連線埠號狀態為 time_wait。在centos上大概1分鐘就可以消失。如果大量連線到來,埠號將不夠使用,同時time_wait還會占用些許資源。所以,最好的情形是讓伺服器不要主動關閉連線,避免進入到time_wait狀態。

【原因2】tcp斷開要經過4次握手,比如上述例子,如果a先關閉呼叫close,則會傳送乙個fin到c,c的協議棧自動返回乙個ack,然後進入close_wait,等待c應用層呼叫close關閉連線。試想,乙個千錘百鍊的服務端程式和多種多樣的客戶端程式,誰的程式更可靠?並且在當前為了可依賴的server儘量減少server邏輯,並且大劑量測試的情形下,我更傾向於信任server,那麼不可靠的client,比如這裡的c,由於程式設計師的粗心忘記呼叫close了,或者某個異常邏輯跳過了close。災難了,伺服器將會儲存許許多多的close_wait這個本來可以不必長久存在的狀態。所以更應該將伺服器端保持被動關閉,因為他會更好的處理4次握手的中間那個容易被遺忘的close函式。

(3)解決

重用time_wait echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

**time_wait echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle    在centos上,會導致客戶端機器無法連線伺服器,任何埠!!!

python筆記 網路程式設計 TCP程式設計(伺服器)

目錄 一 建立伺服器響應 1.1步驟 1.2完整 1.3執行 伺服器程序首先要繫結乙個埠並監聽來自其他客戶端的連線。如果某個客戶端連線過來了,伺服器就與該客戶端建立socket連線,隨後的通訊就靠這個socket連線了。所以,伺服器會開啟固定埠 比如80 監聽,每來乙個客戶端連線,就建立該socke...

網路程式設計 tcp檔案伺服器

客戶端功能如下 1.支援以下命令 help 顯示客戶端所有命令和說明 put 上傳檔案 quit 退出客戶端 伺服器端功能 單程序 解析客戶端命令並提供相應服務 伺服器端 include include include include include include include include ...

MFC Socket網路程式設計之TCP伺服器端

tcp ip與osi7層參考模型的對應關係 osi的第12層也就是物理層 和資料鏈路層 對應於tcp ip的網路介面 osi的第3層網路層對應tcp ip的網路層 osi的傳輸層對應tcp ip的傳輸層 osi的567層也就是會話層,表示層,應用層 對應tcp ip的應用層 osi參考模型並不是真正...