1. TCP保活的必要性服務器
1) 不少防火牆等對於空閒socket自動關閉網絡
2) 對於非正常斷開, 服務器並不能檢測到. 爲了回收資源, 必須提供一種檢測機制.框架
2. 致使TCP斷連的因素socket
若是網絡正常, socket也經過close操做來進行優雅的關閉, 那麼一切完美. 但是有不少狀況, 好比網線故障, 客戶端一側忽然斷電或者崩潰等等, 這些狀況server並不能正常檢測到鏈接的斷開. tcp
3. 保活的兩種方式:ide
1) 應用層面的心跳機制spa
自定義心跳消息頭. 通常客戶端主動發送, 服務器接收後進行迴應(也能夠不迴應). 這裏不進行詳述..net
PS: 有人從軟件的功能角度列出第三種方式, 就是經過第三方軟件來進行探測, 肯定鏈接的有效性. 這種方式侷限性很大, 並且不屬於軟件內部的功能實現. 不進行討論.code
2) TCP協議自帶的保活功能server
打開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
int keepAlive = 1; // 開啓keepalive屬性. 缺省值: 0(關閉)
int keepIdle = 60; // 若是在60秒內沒有任何數據交互,則進行探測. 缺省值:7200(s)
int keepInterval = 5; // 探測時發探測包的時間間隔爲5秒. 缺省值:75(s)
int keepCount = 2; // 探測重試的次數. 所有超時則認定鏈接失效..缺省值:9(次)
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval));
setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));
使用時須要#include <netinet/tcp.h>, 不然SOL_TCP和TCP_KEEPIDLE等3個宏找不到.
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