TCP close wait 狀態的解釋

2021-08-13 20:38:14 字數 2333 閱讀 5270

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 被建立。在這個時候,執行緒剛剛被建立出來,開闢了記憶...