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

2022-09-22 20:03:13 字數 2554 閱讀 4444

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,keepcount3個屬性,使用簡單,如下:

intkeepalive=1;//開啟keepalive屬性.預設值:0(關閉)

intkeepidle=60;//如果在60秒內沒有任何資料互動,則進行探測.預設值:7200(s)

intkeepinterval=5;//探測時發探測包的時間間隔為5秒.預設值:75(s)

intkeepcount=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,否則sol_tcp和tcp_keepidle等3個巨集找不到.

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

2)修改配置檔案,對整個系統所有的socket有效.

我們可以用cat命令檢視到系統中這幾個預設的值.

#cat/proc/sys/net/ipv4/tcp_keepalive_time7200

#cat/proc/sys/net/ipv4/tcp_keepalive_intvl75

#cat/proc/sys/net/ipv4/tcp_keepalive_probes9

修改它們:

#echo60>/proc/sys/net/ipv4/tcp_keepalive_time

#echo5>/proc/sys/net/ipv4/tcp_keepalive_intvl

#echo3>/proc/sys/net/ipv4/tcp_keepalive_probes

tcp鏈結斷開的探測

有資料說,read write都可以探測tcp的斷開,但都不是實時的。但是實際在某些裝置上測試發現,即使開乙個執行緒每隔一小段時間發一次心跳包 write write可能總是成功的,write也不能探測連線已經斷開,而且這個狀態持續很久。所以,如果需要保持和裝置的連線,心跳包需要回覆,如果兩秒內無回...

TCP連線中的TIME WAIT狀態

根據 unix網路程式設計 卷1,tcp的狀態轉換圖可以得知 執行主動關閉的那端 假設客戶端 經歷了time wait狀態,該狀態停留在那個狀態的持續時間是最長分節期 maximum segment lifetime,msl 的兩倍,稱為2msl。time wait狀態的持續時間在1min 4min...

TCP連線中TIME WAIT連線過多

原文 主題tcp ip socket timewait並不是多餘的 在tcp協議被創造,經歷了大量的實際場景實踐之後 timewait 出現了,因為tcp主 動關閉連線的一方需要timewait狀態,它是我們的朋友。這是 unix網路程式設計 的作者 steven對timewait的態度。tcp要保...