優雅關閉socket的方法 SO LINGER

2021-08-10 10:19:54 字數 3284 閱讀 2356

**:

這個引數對應大量短鏈結的伺服器很有必要!

shutdown(fd, shut_rdwr);

struct linger linger;

linger.l_onoff = 1;

linger.l_linger = 0;

setsockopt(fd, sol_socket, so_linger, (char *) &linger, sizeof(linger));

close(fd);

linger.l_linger = 0;

setsockopt(fd, sol_socket, so_linger, (char *) &linger, sizeof(linger));

close(fd);

此選項指定函式close對面向連線的協議如何操作(如tcp)。核心預設close操作是立即返回,如果有資料殘留在套介面緩衝區中則系統將試著將這些資料傳送給對方。

so_linger選項用來改變此預設設定。使用如下結構:

struct linger ;

有下列三種情況:

1、設定 l_onoff為0,則該選項關閉,l_linger的值被忽略,等於核心預設情況,close呼叫會立即返回給呼叫者,如果可能將會傳輸任何未傳送的資料;

2、設定 l_onoff為非0,l_linger為0,則套介面關閉時tcp夭折連線,tcp將丟棄保留在套介面傳送緩衝區中的任何資料並傳送乙個rst給對方,而不是通常的四分組終止序列,這避免了time_wait狀態;

3、設定 l_onoff 為非0,l_linger為非0,當套介面關閉時核心將拖延一段時間(由l_linger決定)。如果套介面緩衝區中仍殘留資料,程序將處於睡眠狀態,直 到(a)所有資料傳送完且被對方確認,之後進行正常的終止序列(描述字訪問計數為0)或(b)延遲時間到。此種情況下,應用程式檢查close的返回值是非常重要的,如果在資料傳送完並被確認前時間到,close將返回ewouldblock錯誤且套介面傳送緩衝區中的任何資料都丟失

。close的成功返回僅告訴我們傳送的資料(和fin)已由對方tcp確認,它並不能告訴我們對方應用程序是否已讀了資料。如果套介面設為非阻塞的,它將不等待close完成。

注釋:l_linger的單位依賴於實現: 4.4bsd假設其單位是時鐘滴答(百分之一秒),但posix.1g規定單位為秒。

下面的**是乙個使用so_linger選項的例子,使用30秒的超時時限:

#define true     1

#define false    0

int z; /* status code

*/ int s;       /* socket s */

struct linger so_linger;

...so_linger.l_onoff = true;

so_linger.l_linger = 30;

z = setsockopt(s,

sol_socket,

so_linger,

&so_linger,

sizeof so_linger);

if ( z )

perror("setsockopt(2)");

下面的例子顯示了如何設定so_linger的值來中止套介面s上的當前連線:

#define true     1

#define false    0

int z; /* status code */

int s;       /* socket s */

struct linger so_linger;

...so_linger.l_onoff = true;

so_linger.l_linger = 0;

z = setsockopt(s,

sol_socket,

so_linger,

&so_linger,

sizeof so_linger);

if ( z )

perror("setsockopt(2)");

close(s); /* abort connection */

在上面的這個例子中,當呼叫close函式時,套介面s會立即中止。中止的語義是通過將超時值設定為0來實現的。

/********** windows **********/

/* 當連線中斷時,需要延遲關閉(linger)以保證所有資料都被傳輸,所以需要開啟so_linger這個選項;  

* //注:大致意思就是說so_linger選項用來設定當呼叫closesocket時是否馬上關閉socket; 

* linger的結構在/usr/include/linux/socket.h中定義://注:這個結構就是setsocketopt中的data的資料結構 

*  struct linger 

*  ; 

*  如果l_onoff為0,則延遲關閉特性就被取消。

*   如果非零,則允許套介面延遲關閉; l_linger欄位則指明延遲關閉的時間 

*/更具體的描述如下:

1、若設定了so_linger(亦即linger結構中的l_onoff域設為非零),並設定了零超時間隔,則closesocket()不被阻塞立即執行,不論是否有排隊資料未傳送或未被確認。這種關閉方式稱為「強制」或「失效」關閉

,因為套介面的虛電路立即被復位,且丟失了未傳送的資料。在遠端的recv()呼叫將以wsaeconnreset出錯。

2、若設定了so_linger並確定了非零的超時間隔,則closesocket()呼叫阻塞程序,直到所剩資料傳送完畢或超時。這種關閉稱為「優雅」或「從容」關閉

。請注意如果套介面置為非阻塞且so_linger設為非零超時,則closesocket()呼叫將以wsaewouldblock錯誤返回。

3、若在乙個流類套介面上設定了so_dontlinger(也就是說將linger結構的l_onoff域設為零),則closesocket()呼叫立即返回。但是,如果可能,排隊的資料將在套介面關閉前傳送。請注意,在這種情況下windows套介面實現將在一段不確定的時間內保留套介面以及其他資源,這對於想用所以套介面的應用程式來說有一定影響。

so_dontlinger 若為真,則so_linger選項被禁止。

so_linger延遲關閉連線 struct linger上面這兩個選項影響close行為;

選項          間隔    關閉方式  等待關閉與否

so_dontlinger   不關心     優雅         否

so_linger        零        強制         否

so_linger       非零       優雅         是

優雅的關閉socket

我們在利用iocp 完成埠 進行程式設計的時候,經常要關閉一些不滿足條件的套接字。假如我們直接採用closesocket方法進行關閉的話,繫結到io埠的此套接字的未傳送的資料就會丟失,這種情況是我們不願意發生的。下面介紹一種合理關閉此套接字的方法 首先,利用setsockopt msdn 函式設定套...

如何優雅地關閉乙個socket

如何優雅地關閉乙個socket 1.關閉socket時究竟做了什麼 關閉socket分為主動關閉 active closure 和被動關閉 passive closure 兩種情況。前者是指有本地主機主動發起的關閉 而後者則是指本地主機檢測到遠端主機發起關閉之後,作出回應,從而關閉整個連線。其狀態圖...

TCP中的優雅關閉和非優雅關閉

優雅關閉 其實就是正常的四次揮手 非優雅關閉 向對端傳送乙個rst報文直接進入closed狀態 伺服器為了避免太多time wait的關閉方式 1.保證由客戶端主動發起關閉 2.關閉的時候使用rst的方式 3.對處於time wait狀態的tcp允許重用 一般我們當然最好是選擇第一種方式,實在沒有辦...