close_wait狀態的生成原因
首先我們知道,如果我們的client程式處於close_wait狀態的話,說明套接字是被動關閉的!
因為如果是server端主動斷掉當前連線的話,那麼雙方關閉這個tcp連線共需要四個packet:
server ---> fin ---> client
server <--- ack <--- client
這時候server端處於fin_wait_2狀態;而我們的程式處於close_wait狀態。
server <--- fin <--- client
這時client傳送fin給server,client就置為last_ack狀態。
server ---> ack ---> client
server回應了ack,那麼client的套接字才會真正置為closed狀態。
我們的程式處於close_wait狀態,而不是last_ack狀態,說明還沒有發fin給server,那麼可能是在關閉連線之前還有許多資料要傳送或者其他事要做,導致沒有發這個fin packet。
原因知道了,那麼為什麼不發fin包呢,難道會在關閉己方連線前有那麼多事情要做嗎?
還有乙個問題,為什麼有數千個連線都處於這個狀態呢?難道那段時間內,伺服器端總是主動拆除我們的連線嗎?
不管怎麼樣,我們必須防止類似情況再度發生!
首先,我們要防止不斷開闢新的埠,這可以通過設定so_reuseaddr套接字選項做到:
重用本地位址和埠
以前我總是乙個埠不行,就換乙個新的使用,所以導致讓數千個埠進入close_wait狀態。如果下次還發生這種尷尬狀況,我希望加乙個限定,只是當前這個埠處於close_wait狀態!
在呼叫sockconnected = socket(af_inet, sock_stream, 0);
之後,我們要設定該套接字的選項來重用:
/// 允許重用本地位址和埠:
/// 這樣的好處是,即使socket斷了,呼叫前面的socket函式也不會占用另乙個,而是始終就是乙個埠
/// 這樣防止socket始終連線不上,那麼按照原來的做法,會不斷地換埠。
int nreuseaddr = 1;
setsockopt(sockconnected,
sol_socket,
so_reuseaddr,
(const char*)&nreuseaddr,
sizeof(int));
教科書上是這麼說的:這樣,假如伺服器關閉或者退出,造成本地位址和埠都處於time_wait狀態,那麼so_reuseaddr就顯得非常有用。
也許我們無法避免被凍結在close_wait狀態永遠不出現,但起碼可以保證不會占用新的埠。
其次,我們要設定so_linger套接字選項:
從容關閉還是強行關閉?
linger是「拖延」的意思。
預設情況下(win2k),so_dontlinger套接字選項的是1;so_linger選項是,linger為。
如果在傳送資料的過程中(send()沒有完成,還有資料沒傳送)而呼叫了closesocket(),以前我們一般採取的措施是「從容關閉」:
因為在退出服務或者每次重新建立socket之前,我都會先呼叫
/// 先將雙向的通訊關閉
shutdown(sockconnected, sd_both);
/// 安全起見,每次建立socket連線前,先把這個舊連線關閉
closesocket(sockconnected);
我們這次要這麼做:
設定so_linger為零(亦即linger結構中的l_onoff域設為非零,但l_linger為0),便不用擔心closesocket呼叫進入「鎖定」狀態(等待完成),不論是否有排隊資料未傳送或未被確認。這種關閉方式稱為「強行關閉」,因為套接字的虛電路立即被復位,尚未發出的所有資料都會丟失。在遠端的recv()呼叫都會失敗,並返回wsaeconnreset錯誤。
在connect成功建立連線之後設定該選項:
linger m_slinger;
m_slinger.l_onoff = 1; // (在closesocket()呼叫,但是還有資料沒傳送完畢的時候容許逗留)
m_slinger.l_linger = 0; // (容許逗留的時間為0秒)
setsockopt(sockconnected,
sol_socket,
so_linger,
(const char*)&m_slinger,
sizeof(linger));
總結也許我們避免不了close_wait狀態凍結的再次出現,但我們會使影響降到最小,希望那個重用套接字選項能夠使得下一次重新建立連線時可以把close_wait狀態踢掉
8程序的狀態和狀態轉換
一 程序的狀態 二 程序狀態間的轉換 1 程序 程式的一次執行過程,從開始到結束 2 狀態引入 因為程序在執行中,有時被cup處理 有時需要等待cpu服務,因此程序的狀態會有各種變化,為了方便對各個程序進行管理 作業系統將程序分為幾種狀態 3 程序的狀態 建立態 程序正在被建立,作業系統為程序分配資...
Flink的狀態管理與狀態後端
flink是乙個基於狀態計算的流計算服務。flink將所有的狀態分為兩大類 keyed state 與 operator state 所謂的keyed state指的是flink底層會給每乙個key繫結若干個型別的狀態值,特指操作 keyedstream中所涉及的狀態。所謂operator stat...
執行緒的狀態
執行緒的狀態 概念 乙個時刻,cpu只能運算乙個執行緒的任務。對於執行緒來說,有cpu的執行資格或者cpu的執行權。cpu的執行資格 可以被cpu處理,但還沒有輪到自己,在處理佇列中排隊。cpu的執行權 正在獲取cpu的資格 執行緒有五種狀態 1 被建立。在這個時候,執行緒剛剛被建立出來,開闢了記憶...