Socket心跳包機制

<轉(zhuǎn)自CSDN技術(shù)博客>
心跳包的發(fā)送,通常有兩種技術(shù)
方法1:應(yīng)用層自己實現(xiàn)的心跳包
由應(yīng)用程序自己發(fā)送心跳包來檢測連接是否正常,大致的方法是:服務(wù)器在一個 Timer事件中定時 向客戶端發(fā)送一個短小精悍的數(shù)據(jù)包,然后啟動一個低級別的線程,在該線程中不斷檢測客戶端的回應(yīng), 如果在一定時間內(nèi)沒有收到客戶端的回應(yīng),即認(rèn)為客戶端已經(jīng)掉線;同樣,如果客戶端在一定時間內(nèi)沒 有收到服務(wù)器的心跳包,則認(rèn)為連接不可用。

方法2:TCP的KeepAlive?;顧C制
因為要考慮到一個服務(wù)器通常會連接多個客戶端,因此由用戶在應(yīng)用層自己實現(xiàn)心跳包,代碼較多 且稍顯復(fù)雜,而利用TCP/IP協(xié)議層為內(nèi)置的KeepAlive功能來實現(xiàn)心跳功能則簡單得多。 不論是服務(wù)端還是客戶端,一方開啟KeepAlive功能后,就會自動在規(guī)定時間內(nèi)向?qū)Ψ桨l(fā)送心跳包, 而另一方在收到心跳包后就會自動回復(fù),以告訴對方我仍然在線。 因為開啟KeepAlive功能需要消耗額外的寬帶和流量,所以TCP協(xié)議層默認(rèn)并不開啟KeepAlive功 能,盡管這微不足道,但在按流量計費的環(huán)境下增加了費用,另一方面,KeepAlive設(shè)置不合理時可能會 因為短暫的網(wǎng)絡(luò)波動而斷開健康的TCP連接。并且,默認(rèn)的KeepAlive超時需要7,200,000 MilliSeconds, 即2小時,探測次數(shù)為5次。對于很多服務(wù)端應(yīng)用程序來說,2小時的空閑時間太長。因此,我們需要手工開啟KeepAlive功能并設(shè)置合理的KeepAlive參數(shù)。
以上轉(zhuǎn)自網(wǎng)絡(luò)。

心跳包機制
跳包之所以叫心跳包是因為:它像心跳一樣每隔固定時間發(fā)一次,以此來告訴服務(wù)器,這個客戶端還活著。事實上這是為了保持長連接,至于這個包的內(nèi)容,是沒有什么特別規(guī)定的,不過一般都是很小的包,或者只包含包頭的一個空包。 在TCP的機制里面,本身是存在有心跳包的機制的,也就是TCP的選項:SO_KEEPALIVE。系統(tǒng)默認(rèn)是設(shè)置的2小時的心跳頻率。但是它檢查不到機器斷電、網(wǎng)線拔出、防火墻這些斷線。而且邏輯層處理斷線可能也不是那么好處理。一般,如果只是用于?;钸€是可以的。 心跳包一般來說都是在邏輯層發(fā)送空的echo包來實現(xiàn)的。下一個定時器,在一定時間間隔下發(fā)送一個空包給客戶端,然后客戶端反饋一個同樣的空包回來,服務(wù)器如果在一定時間內(nèi)收不到客戶端發(fā)送過來的反饋包,那就只有認(rèn)定說掉線了。 其實,要判定掉線,只需要send或者recv一下,如果結(jié)果為零,則為掉線。但是,在長連接下,有可能很長一段時間都沒有數(shù)據(jù)往來。理論上說,這個連接是一直保持連接的,但是實際情況中,如果中間節(jié)點出現(xiàn)什么故障是難以知道的。更要命的是,有的節(jié)點(防火墻)會自動把一定時間之內(nèi)沒有數(shù)據(jù)交互的連接給斷掉。在這個時候,就需要我們的心跳包了,用于維持長連接,保活。 在獲知了斷線之后,服務(wù)器邏輯可能需要做一些事情,比如斷線后的數(shù)據(jù)清理呀,重新連接呀……當(dāng)然,這個自然是要由邏輯層根據(jù)需求去做了。 總的來說,心跳包主要也就是用于長連接的?;詈蛿嗑€處理。一般的應(yīng)用下,判定時間在30-40秒比較不錯。如果實在要求高,那就在6-9秒。

心跳檢測步驟:1客戶端每隔一個時間間隔發(fā)生一個探測包給服務(wù)器2客戶端發(fā)包時啟動一個超時定時器3服務(wù)器端接收到檢測包,應(yīng)該回應(yīng)一個包4如果客戶機收到服務(wù)器的應(yīng)答包,則說明服務(wù)器正常,刪除超時定時器5如果客戶端的超時定時器超時,依然沒有收到應(yīng)答包,則說明服務(wù)器掛了轉(zhuǎn)自:http://blog.sina.com.cn/s/blog_a459dcf5010153m5.html
根據(jù)上面的介紹我們可以知道對端以一種非優(yōu)雅的方式斷開連接的時候,我們可以設(shè)置SO_KEEPALIVE屬性使得我們在2小時以后發(fā)現(xiàn)對方的TCP連接是否依然存在。具體操作:
//設(shè)置KeepAlive
1、

BOOL   bKeepAlive   =   TRUE;       
  int nRet=::
setsockopt(sockClient,SOL_SOCKET,SO_KEEPALIVE,(char*)&bKeepAlive,sizeof(bKeepAlive));  
       if(nRet!=0)        {            
 AfxMessageBox("出錯");  
       return   ;   
 }            
2、感覺兩小時時間太長可以自行設(shè)定方法1 //設(shè)置KeepAlive檢測時間和次數(shù)       
  tcp_keepalive    inKeepAlive   =   {0};   //輸入?yún)?shù)        
 unsigned   long   ulInLen   =   sizeof(tcp_keepalive );             
    tcp_keepalive    outKeepAlive   =   {0};   //輸出參數(shù)        
 unsigned   long   ulOutLen   =   sizeof(tcp_keepalive );              
   unsigned   long   ulBytesReturn   =   0;            
 //設(shè)置socket的keep   alive為10秒,并且發(fā)送次數(shù)為3次        
 inKeepAlive.onoff   =   1;           
inKeepAlive.keepaliveinterval   =   4000;  
 //兩次KeepAlive探測間的時間間隔         
inKeepAlive.keepalivetime   =   1000;   
//開始首次KeepAlive探測前的TCP空閉時間             
nRet=WSAIoctl(sockClient,               
SIO_KEEPALIVE_VALS,             
(LPVOID)&inKeepAlive,             
ulInLen,             
(LPVOID)&outKeepAlive,             
ulOutLen,     &ulBytesReturn,        NULL,             NULL);       
 if(SOCKET_ERROR   ==   nRet)         {          
   AfxMessageBox("出錯");      
  return;      
  }  
 3、感覺兩小時時間太長可以自行設(shè)定方法2因此我們可以得到    
int                 keepIdle = 6;   
 int                 keepInterval = 5;    
int                 keepCount = 3;   
 Setsockopt(listenfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));    
Setsockopt(listenfd, SOL_TCP,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));    
Setsockopt(listenfd,SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

詳見:http://blog.csdn.net/gavin1203/article/details/5290609setsockopt的操作,
詳見:http://www.cnblogs.com/hateislove214/archive/2010/11/05/1869886.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容