socket使用者異常掉線檢測

2021-06-08 16:46:31 字數 3101 閱讀 2557

**:socket使用者異常掉線檢測

目前主要有三種方法來實現使用者掉線檢測:so_keepalive ,sio_keepalive_vals 和heart-beat執行緒。

下面我就上面的三種方法來做一下介紹。

(1)so_keepalive 機制 

這是socket庫提供的功能,設定介面是setsockopt api:

bool  bset=true;

setsockopt(hsocket,sol_socket,so_keepalive,(const char*)&bset,sizeof(bool));

根據msdn的文件,如果為socket設定了keepalive選項,tcp/ip棧在檢測到對方掉線後,

任何在該socket上進行的呼叫(傳送/接受呼叫)就會立刻返回,錯誤號是wsaenetreset ;

同時,此後的任何在該socket控制代碼的呼叫會立刻失敗,並返回wsaenotconn錯誤。

該機制的缺點也很明顯:

預設設定是空閒2小時才傳送乙個「保持存活探測分節」,不能保證實時檢測!

當然也可以修改時間間隔引數,但是會影響到所有開啟此選項的套介面!

關聯了完成埠的socket可能會忽略掉該套接字選項。

(2)sio_keepalive_vals 機制 

這是從彭博兄那裡學到乙個機制拉,設定介面是wsaioctl api:

dword dwerror = 0l ;

tcp_keepalive ska_settings = , sreturned = ;

ska_settings.onoff = 1 ;

ska_settings.keepalivetime = 5500 ; // keep alive in 5.5 sec.

ska_settings.keepaliveinterval = 3000 ; // resend if no-reply

if (wsaioctl(sknewconnection, sio_keepalive_vals, &ska_settings,

sizeof(ska_settings), &sreturned, sizeof(sreturned), &dwbytes,

null, null) != 0)

實現時需要新增tcp_keepalive and sio_keepalive_vals的定義檔案mstcpip.h 

該選項不同於so_keepalive 機制的就是它是針對單個連線的,對系統其他的套接

口並不影響。

針對完成埠的socket,設定了sio_keepalive_vals後,啟用包由tcp stack來負責。

當網路連線斷開後,tcp stack並不主動告訴上層的應用程式,但是當下一次recv或者send操作

進行後,馬上就會返回錯誤告訴上層這個連線已經斷開了.如果檢測到斷開的時候,在這個連線

上有正在pending的io操作,則馬上會失敗返回. 

該機制的缺點:

優雅一些^_^.

(3)heart-beat執行緒

沒說的。自己寫乙個後台執行緒,實現heart-beat包,客戶端受到該包後,立刻返回相應的反饋  包。 

該方法的好處是通用,但缺點就是會改變現有的通訊協議!

有開發網路應用經歷的人都知道,網路中的接收和傳送資料都是使用windows中的socket進行實現。但是如果此套接字已經斷開,那傳送資料和接收資料的時候就一定會有問題。可是如何判斷這個套接字是否還可以使用呢? 

有人一定想到使用send函式中的返回結果來進行判斷。如果返回的長度和自己傳送出去的長度一致,那就說明這個套接字是可用的,否則此套接字一定出現了問題。但是我們並不是無時無刻的傳送資料呀。如何解決呢? 

其實tcp中已經為我們實現了乙個叫做心跳的機制。如果你設定了心跳,那tcp就會在一定的時間(比如你設定的是3秒鐘)內傳送你設定的次數的心跳(比如說2次),並且此資訊不會影響你自己定義的協議。 

在vc中實現心跳的例子很多,可是在dlephi中一直沒有相應的**。下面我是我使用delphi編寫的關於心跳的**(以iocp為例),希望對大家有幫助。 

定義心跳常量 

const

ioc_in               =$80000000;

ioc_vendor           =$18000000;

ioc_out              =$40000000;

sio_keepalive_vals   =ioc_in or ioc_vendor or 4; 

var 

inkeepalive,outkeepalive:ttcp_keepalive; 

實現**是在acceptsc:= wsaaccept(listensc, nil, nil, nil, 0);**的後面加入: 

opt:=1;

if setsockopt(acceptsc,sol_socket,so_keepalive,@opt,sizeof(opt))=socket_error then

begin

closesocket(acceptsc);

end;

inkeepalive.onoff:=1;

//設定3秒鐘時間間隔 

inkeepalive.keepalivetime:=3000; 

//設定每3秒中傳送1次的心跳

inkeepalive.keepaliveinterval:=1;

insize:=sizeof(ttcp_keepalive);

outsize:=sizeof(ttcp_keepalive);

if wsaioctl(accept,sio_keepalive_vals,@inkeepalive,insize,@outkeepalive,outsize,@outbyte,nil,nil)=socket_error then

begin

closesocket(acceptsc);

end; 

如果加入以上的**以後,系統會每3秒中加入一次的心跳。並且如果客戶端斷線以後(網線斷),函式getqueuedcompletionstatus會返回false。 

begin

//在這裡處理客戶端斷線資訊。 

continue;

end; 

以上就是我使用心跳的方法,此方法我已經在我的網路遊戲中使用。情況穩定!

socket使用者異常掉線檢測

2012 03 30 17 05 62人閱讀收藏 舉報目前主要有三種方法來實現使用者掉線檢測 so keepalive sio keepalive vals 和heart beat執行緒。下面我就上面的三種方法來做一下介紹。1 so keepalive 機制 這是socket庫提供的功能,設定介面是...

socket選項自帶的TCP異常斷開檢測

tcp異常斷開是指在突然斷電,直接拔網線等等情況下,如果通訊雙方沒有進行資料傳送通訊等處理的時候,無法獲知連線已經斷開的情況.在通常的情況下,為了使得socket通訊不受作業系統的限制,需要自己在應用層實現心跳包機制,來檢查異常斷開的情況,一般的方式就是伺服器在一段時間沒有收到客戶端資料報時,定時發...

socket選項自帶的TCP異常斷開檢測

tcp異常斷開是指在突然斷電,直接拔網線等等情況下,如果通訊雙方沒有進行資料傳送通訊等處理的時候,無法獲知連線已經斷開的情況.在通常的情況下,為了使得socket通訊不受作業系統的限制,需要自己在應用層實現心跳包機制,來檢查異常斷開的情況,一般的方式就是伺服器在一段時間沒有收到客戶端資料報時,定時發...