如何在socket程式設計的Tcp連線中實現心跳協議

2021-08-21 05:54:15 字數 2534 閱讀 9678

跳包之所以叫心跳包是因為:它像心跳一樣每隔固定時間發一次,以此來告訴伺服器,這個客戶端還活著。事實上這是為了保持長連線,至於這個包的內容,是沒有什麼特別規定的,不過一般都是很小的包,或者只包含包頭的乙個空包。

在tcp的機制裡面,本身是存在有心跳包的機制的,也就是tcp的選項:so_keepalive。系統預設是設定的2小時的心跳頻率。但是它檢查不到機器斷電、網線拔出、防火牆這些斷線。而且邏輯層處理斷線可能也不是那麼好處理。一般,如果只是用於保活還是可以的。

心跳包一般來說都是在邏輯層傳送空的echo包來實現的。下乙個定時器,在一定時間間隔下傳送乙個空包給客戶端,然後客戶端反饋乙個同樣的空包回來,伺服器如果在一定時間內收不到客戶端傳送過來的反饋包,那就只有認定說掉線了。

其實,要判定掉線,只需要send或者recv一下,如果結果為零,則為掉線。但是,在長連線下,有可能很長一段時間都沒有資料往來。理論上說,這個連線是一直保持連線的,但是實際情況中,如果中間節點出現什麼故障是難以知道的。更要命的是,有的節點(防火牆)會自動把一定時間之內沒有資料互動的連線給斷掉。在這個時候,就需要我們的心跳包了,用於維持長連線,保活。

在獲知了斷線之後,伺服器邏輯可能需要做一些事情,比如斷線後的資料清理呀,重新連線呀……當然,這個自然是要由邏輯層根據需求去做了。

總的來說,心跳包主要也就是用於長連線的保活和斷線處理。一般的應用下,判定時間在30-40秒比較不錯。如果實在要求高,那就在6-9秒。

心跳檢測步驟:

1客戶端每隔乙個時間間隔發生乙個探測包給伺服器

2客戶端發包時啟動乙個超時定時器

3伺服器端接收到檢測包,應該回應乙個包

4如果客戶機收到伺服器的應答包,則說明伺服器正常,刪除超時定時器

5如果客戶端的超時定時器超時,依然沒有收到應答包,則說明伺服器掛了

**:根據上面的介紹我們可以知道對端以一種非優雅的方式斷開連線的時候,我們可以設定so_keepalive屬性使得我們在2小時以後發現對方的tcp連線是否依然存在。

具體操作:

//設定keepalive     

1、 bool   bkeepalive   =   true;     

int nret=::setsockopt(sockclient,sol_socket,so_keepalive,(char*)&bkeepalive,sizeof(bkeepalive));     

if(nret!=0)    

2、感覺兩小時時間太長可以自行設定方法1 

//設定keepalive檢測時間和次數     

tcp_keepalive    inkeepalive   =   ;   //輸入引數     

unsigned   long   ulinlen   =   sizeof(tcp_keepalive );         

tcp_keepalive    outkeepalive   =   ;   //輸出引數     

unsigned   long   uloutlen   =   sizeof(tcp_keepalive );         

unsigned   long   ulbytesreturn   =   0;     

//設定socket的keep   alive為10秒,並且傳送次數為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)     

3、感覺兩小時時間太長可以自行設定方法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));

Socket 程式設計(TCP)

詳細請參見 點我o o哈!很不錯的一篇文章哈 下面是接收資料和傳送資料的函式 int receive socket fd,char sztext,int len if rc 0 return len cnt sztext rc cnt rc return len int send socket fd...

Socket 程式設計(TCP)

下面是接收資料和傳送資料的函式 cpp view plain copy intreceive socket fd,char sztext,intlen if rc 0 return len cnt sztext rc cnt rc return len int send socket fd,char...

socket程式設計TCP

注意一定要先啟動server,再啟動client,否則client因為無法找到server而丟擲異常 coding utf 8 from socket import serverport 12000 af inet表示底層網路使用的是ipv4,sock stream表示使用的socket型別是tcp...