目前主要有三種方法來實現使用者掉線檢測: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操作,則馬上會失敗返回.
該方法的好處是通用,但缺點就是會改變現有的通訊協議!
**:參考2:
檢測socket鏈結是否斷開
解決方案 1.傳送重試,由業務完成。因為club l5的send介面不會保留使用者傳送的內容,在recv失敗的情況下,使用者傳送的資料已經丟失,所以只能由業務進行重試。結論 否定。由於後端伺服器有多台,每次傳送的時候並不能不能保證連線的機器還是上次傳送的那一台伺服器,有可能後端所有的連線都被斷開,雖...
自動檢測SOCKET鏈結斷開
如何判斷socket已經斷開 最近在做乙個伺服器端程式,c s結構。功能方面比較簡單就是client端與server端建立連線,然後傳送訊息給server。我在server端會使用專門的執行緒處理一條socket連線。這就涉及到乙個問題,如果socket連線斷開 異常,正常 後,我如何才能感知到?s...
Socket程式設計中檢測埠是否被占用
一般檢測乙個埠是否被占用的方法是看bind是否成功,其實在windows中有兩個api可以獲取到當前系統埠的占用情況 gettcptable getudptable 利用這兩個函式就可檢測埠占用情況。但在較複雜系統環境下,埠占用表可能隨時改變,可能存在兩個以上程序使用上述方法檢測到同一空閒埠,在這種...