程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> tcp連接探測Keepalive和心跳包

tcp連接探測Keepalive和心跳包

編輯:關於C++

采用TCP連接的C/S模式軟件,連接的雙方在連接空閒狀態時,如果任意一方意外崩潰、當機、網線斷開或路由器故障,另一方無法得知TCP連接已經失效,除非繼續在此連接上發送數據導致錯誤返回。很多時候,這不是我們需要的。我們希望服務器端和客戶端都能及時有效地檢測到連接失效,然後優雅地完成一些清理工作並把錯誤報告給用戶。

如何及時有效地檢測到一方的非正常斷開,一直有兩種技術可以運用。一種是由TCP協議層實現的Keepalive,另一種是由應用層自己實現的心跳包。

TCP默認並不開啟Keepalive功能,因為開啟Keepalive功能需要消耗額外的寬帶和流量,盡管這微不足道,但在按流量計費的環境下增加了費用,另一方面,Keepalive設置不合理時可能會因為短暫的網絡波動而斷開健康的TCP連接。並且,默認的Keepalive超時需要7,200,000 milliseconds,即2小時,探測次數為5次。

對於Win2K/XP/2003,可以從下面的注冊表項找到影響整個系統所有連接的keepalive參數:

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters]

"KeepAliveTime”=dword:006ddd00

"KeepAliveInterval"=dword:000003e8

"MaxDataRetries"="5"

對於實用的程序來說,2小時的空閒時間太長。因此,我們需要手工開啟Keepalive功能並設置合理的Keepalive參數。

// 開啟KeepAlive

BOOL bKeepAlive = TRUE;

int nRet = ::setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));

if (nRet == SOCKET_ERROR)

{

return FALSE;

}

// 設置KeepAlive參數

tcp_keepalive alive_in = {0};

tcp_keepalive alive_out = {0};

alive_in.keepalivetime = 5000; // 開始首次KeepAlive探測前的TCP空閉時間

alive_in.keepaliveinterval = 1000; // 兩次KeepAlive探測間的時間間隔

alive_in.onoff = TRUE;

unsigned long ulBytesReturn = 0;

nRet = WSAIoctl(socket_handle, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),

&alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);

if (nRet == SOCKET_ERROR)

{

return FALSE;

}

開啟Keepalive選項之後,對於使用IOCP模型的服務器端程序來說,一旦檢測到連接斷開,GetQueuedCompletionStatus函數將立即返回FALSE,使得服務器端能及時清除該連接、釋放該連接相關的資源。對於使用select模型的客戶端來說,連接斷開被探測到時,以recv目的阻塞在socket上的select方法將立即返回SOCKET_ERROR,從而得知連接已失效,客戶端程序便有機會及時執行清除工作、提醒用戶或重新連接。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved