TCP連接探測中的Keepalive和心跳包

1. TCP保活的必要性

1) 很多防火牆等對於空閒socket自動關閉

2) 對於非正常斷開服務器並不能檢測到爲了回收資源必須提供一種檢測機制.


2. 導致TCP斷連的因素

如果網絡正常, socket也通過close操作來進行優雅的關閉那麼一切完美可是有很多情況比如網線故障客戶端一側突然斷電或者崩潰等等這些情況server並不能正常檢測到連接的斷開


3. 保活的兩種方式:

1) 應用層面的心跳機制

自定義心跳消息頭一般客戶端主動發送服務器接收後進行迴應(也可以不迴應). 這裏不進行詳述.

PS: 有人從軟件的功能角度列出第三種方式就是通過第三方軟件來進行探測確定連接的有效性這種方式侷限性很大而且不屬於軟件內部的功能實現不進行討論.

2) TCP協議自帶的保活功能

打開keep-alive功能即可具體屬性也可以通過API設定.


4. 兩種方式的優劣性

TCP協議自帶的保活功能使用起來簡單減少了應用層代碼的複雜度推測也會更節省流量因爲一般來說應用層的數據傳輸到協議層時都會被加上額外的包頭包尾TCP協議提供的檢活其發的探測包理論上實現的會更精妙(用更少的字節完成更多的目標), 耗費更少的流量.

由應用自己實現的應用層的心跳爲心跳消息額外定義一個消息類型就可以了就是應用正常的消息包只是這個包特殊點專門用來檢活而已通常比較小可能只有消息頭就可以了除非需要額外的信息

應用層心跳的好處我個人的理解有兩點

一是比較靈活因爲協議層的心跳只能提供最純粹的檢活功能但是應用層自己可以隨意控制包括協議可能提供的是秒級的但是你想做成毫秒級的都任意(雖然實際幾乎不會有這種時間級別的心跳), 包裏還甚至可以攜帶額外的信息這些都是靈活之處.

二是通用應用層的心跳不依賴協議如果有一天不用TCP要改爲UDP協議層不提供心跳機制了但是你應用層的心跳依舊是通用的可能只需要做少許改動就可以繼續使用.

應用層心跳的不好的地方也很顯而易見增加開發工作量由於應用特定的網絡框架還可能很增加代碼結構的複雜度再就是根據上面的推測應用層心跳的流量消耗還是更大的畢竟這本質上還是個普通的數據包.


5. 到底選用那種心跳方式?

優劣點第4節已經進行了闡述因此如果能確定你們更換協議的可能性非常小同時只是需要檢活的功能那麼用協議自帶的就絕對OK使用簡單而且高效有些自負的人總喜歡用自己搞的來代替成熟協議自帶的東西代替系統內核提供的東西其實往往你應用層實現的東西都是更拙劣的網上看了一些關於協議的Keep-alive不靠譜的說法也都比較空想和想當然都沒有拿出任何事實論據或實驗數據這點大家有見解歡迎交流哈~


6. 類Unix平臺如何使用Keep-alive

keepalive默認是關閉的因爲雖然流量極小畢竟是開銷因此需要用戶手動開啓有兩種方式開啓.

1) 在代碼裏針對每個socket進行單獨設定使用起來靈活.

除了keepAlive 開關還有keepIdle, keepInterval, keepCount 3個屬性使用簡單如下:

[cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片

  1. int keepAlive = 1;   // 開啓keepalive屬性. 缺省值: 0(關閉)  

  2. int keepIdle = 60;   // 如果在60秒內沒有任何數據交互,則進行探測. 缺省值:7200(s)  

  3. int keepInterval = 5;   // 探測時發探測包的時間間隔爲5秒. 缺省值:75(s)  

  4. int keepCount = 2;   // 探測重試的次數. 全部超時則認定連接失效..缺省值:9(次)  

  5. setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));  

  6. setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));  

  7. setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval));  

  8. setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));  

使用時需要#include <netinet/tcp.h>, 否則SOL_TCPTCP_KEEPIDLE3個宏找不到.

ps: 忍不住吐槽一下, 網上大量毫不負責的轉載, 千篇一律的搜索結果, 很多人根本都沒進行過任何驗證吧. 爲了找這麼個頭文件都費了不小的事. 大多數帖子裏的說的都是不可用的.

2) 修改配置文件對整個系統所有的socket有效.

我們可以用cat命令查看到系統中這幾個默認的值.

#cat /proc/sys/net/ipv4/tcp_keepalive_time  7200  

#cat /proc/sys/net/ipv4/tcp_keepalive_intvl  75  

#cat /proc/sys/net/ipv4/tcp_keepalive_probes  9

修改它們:

#echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time  

#echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl  

#echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章