tcp keepalive,Tcp keepalive詳解

 2023-11-09 阅读 23 评论 0

摘要:轉載:https://www.cnblogs.com/lanyangsh/p/10926806.html TCP是面向連接的,一般情況,兩端的應用程序可以通過發送和接收數據得知對端的存活。 當兩端的應用程序都沒有數據發送和接收時,如何判斷連接是否正常呢? 這就是SO_KEEPALIVE的作用

轉載:https://www.cnblogs.com/lanyangsh/p/10926806.html

TCP是面向連接的,一般情況,兩端的應用程序可以通過發送和接收數據得知對端的存活。
當兩端的應用程序都沒有數據發送和接收時,如何判斷連接是否正常呢?

這就是SO_KEEPALIVE的作用。

1. SO_KEEPALIVE 的作用

1.1 SO_KEEPALIVE的定義

tcp keepalive、SO_KEEPALIVE用于開啟或者關閉保活探測,默認情況下是關閉的。

SO_KEEPALIVE開啟時,可以保持連接檢測對方主機是否崩潰,避免(服務器)永遠阻塞于TCP連接的輸入。

相關的屬性包括:
tcp_keepalive_timetcp_keepalive_probestcp_keepalive_intvl

tcp_keepalive_intvl (integer; default: 75; since Linux 2.4)The number of seconds between TCP keep-alive probes.tcp_keepalive_probes (integer; default: 9; since Linux 2.2)The maximum number of TCP keep-alive probes to send beforegiving up and killing the connection if no response isobtained from the other end.tcp_keepalive_time (integer; default: 7200; since Linux 2.2)The number of seconds a connection needs to be idle before TCPbegins sending out keep-alive probes.  Keep-alives are sentonly when the SO_KEEPALIVE socket option is enabled.  Thedefault value is 7200 seconds (2 hours).  An idle connectionis terminated after approximately an additional 11 minutes (9probes an interval of 75 seconds apart) when keep-alive isenabled.Note that underlying connection tracking mechanisms andapplication timeouts may be much shorter.

這些屬性可以在/proc/sys/net/ipv4/下查看:

cat /proc/sys/net/ipv4/tcp_keepalive_time
7200cat /proc/sys/net/ipv4/tcp_keepalive_probes
9cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75

tcp close。也可以通過命令行查看:

sudo sysctl -a | grep keepalivenet.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

1.2 連接探活的過程

開啟SO_KEEPALIVE后,如果2小時內在此套接口的任一方向都沒有數據交換,TCP就自動給對方發一個保持存活探測分節(keepalive probe)。這是一個對方必須響應的TCP分節.

它會導致以下三種情況:

  • 對方接收一切正常:以期望的ACK響應。2小時后,TCP將發出另一個探測分節。
  • 對方已崩潰且已重新啟動:以RST響應。套接口的待處理錯誤被置為ECONNRESET,套接 口本身則被關閉。
  • 對方無任何響應:源自berkeley的TCP發送另外8個探測分節,相隔75秒一個,試圖得到一個響應。一共嘗試9次,即在發出第一個探測分節11分鐘 15秒后若仍無響應就放棄。套接口的待處理錯誤被置為ETIMEOUT,套接口本身則被關閉。如ICMP錯誤是“host unreachable(主機不可達)”,說明對方主機并沒有崩潰,但是不可達,這種情況下待處理錯誤被置為 EHOSTUNREACH。

根據上面的介紹我們可以知道對端以一種非優雅的方式斷開連接的時候,我們可以設置SO_KEEPALIVE屬性使得我們在2小時以后發現對方的TCP連接是否依然存在。

int keepAlive = 1;setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));

tcp全局同步現象?如果我們不能接受如此之長的等待時間,怎么辦?

2.設置TCP KEEPALIVE

上面提到,SO_KEEPALIVE默認的時間間隔太長,不利于應用程序檢測連接狀態。

解決方法有2種:

  • 全局設置
  • 針對單個連接設置

2.1 全局設置

在Linux中我們可以通過修改 /etc/sysctl.conf 的全局配置:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9

添加上面的配置后輸入?sysctl -p?使其生效,
你可以使用命令來查看當前的默認配置

sysctl -a | grep keepalive 

如果應用中已經設置SO_KEEPALIVE,程序不用重啟,內核直接生效.

這種方法設置的全局的參數,針對整個系統生效,對單個socket的設置不夠友好。

2.2 針對單個連接設置

我們可以使用TCP的TCP_KEEPCNTTCP_KEEPIDLETCP_KEEPINTVL3個選項。
這些選項是連接級別的,每個socket都可以設置這些屬性。

這些選項的定義,可以通過man查看。

man 7 tcp

socket option:

TCP_KEEPCNT (since Linux 2.4)The maximum number of keepalive probes TCP should send beforedropping the connection.  This option should not be used incode intended to be portable.關閉一個非活躍連接之前的最大重試次數。該選項不具備可移植性。TCP_KEEPIDLE (since Linux 2.4)The time (in seconds) the connection needs to remain idlebefore TCP starts sending keepalive probes, if the socketoption SO_KEEPALIVE has been set on this socket.  This optionshould not be used in code intended to be portable.設置連接上如果沒有數據發送的話,多久后發送keepalive探測分組,單位是秒該選項不具備可移植性。TCP_KEEPINTVL (since Linux 2.4)The time (in seconds) between individual keepalive probes.This option should not be used in code intended to beportable.前后兩次探測之間的時間間隔,單位是秒該選項不具備可移植性。

代碼層面的設置步驟:

int keepAlive = 1;    // 非0值,開啟keepalive屬性int keepIdle = 60;    // 如該連接在60秒內沒有任何數據往來,則進行此TCP層的探測int keepInterval = 5; // 探測發包間隔為5秒int keepCount = 3;        // 嘗試探測的最多次數// 開啟探活
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount) 

3.為什么應用層需要heart beat/心跳包?

通過上面的介紹,感覺TCP keepalive已經很牛逼了,但為什么還會提到應用層的心跳呢?

目前了解的原因包括兩個:

  • TCP keepalive處于傳輸層,由操作系統負責,能夠判斷進程存在,網絡通暢,但無法判斷進程阻塞或死鎖等問題。
  • 客戶端與服務器之間有四層代理或負載均衡,即在傳輸層之上的代理,只有傳輸層以上的數據才被轉發,例如socks5等

所以,基于以上原因,有時候還是需要應用程序自己去設計心跳規則的。
可以服務端負責周期發送心跳包,檢測客戶端,也可以客戶端負責發送心跳包,或者服服務端和客戶端同時發送心跳包。

可以根據具體的應用場景進行設計。

為什么TCP keepalive不能代替應用層心跳?

心跳說明應用程序還活著(進程還在,網絡通常),更重要的是表明應用程序還能正常工作。而TCP keepalive由操作系統負責探查,即便進程死鎖或阻塞,操作系統也會如常收發TCP keepalive消息。對方無法得知這一異常。

4.TCP Keepalive?HTTP Keep-Alive 的關系

TCP Keepalive?HTTP Keep-Alive 的關系
很多人會把TCP Keepalive 和 HTTP Keep-Alive 這兩個概念搞混淆。

這里簡單介紹下HTTP Keep-Alive 。

在HTTP/1.0中,默認使用的是短連接。也就是說,瀏覽器和服務器每進行一次HTTP操作,就建立一次連接,但任務結束就中斷連接。如果客戶端瀏覽器訪問的某個HTML或其他類型的 Web頁中包含有其他的Web資源,如JavaScript文件、圖像文件、CSS文件等;當瀏覽器每遇到這樣一個Web資源,就會建立一個HTTP會話。

但從 HTTP/1.1起,默認使用長連接,用以保持連接特性。使用長連接的HTTP協議,會在響應頭加上Connection、Keep-Alive字段.如下圖所示

HTTP 1.0 和 1.1 在 TCP連接使用方面的差異如下圖所示

上面說明后,其實就可以知道這兩者的區別了。

HTTP協議的Keep-Alive意圖在于TCP連接復用,同一個連接上串行方式傳遞請求-響應數據;TCP的Keepalive機制意圖在于探測連接的對端是否存活。

參考

《UNIX網絡編程卷1》
《Linux多線程服務端編程》

man 7 tcp

setsockopt, SO_KEEPALIVE and Heartbeats

為什么基于TCP的應用需要心跳包(TCP keep-alive原理分析

TCP中已有SO_KEEPALIVE選項,為什么還要在應用層加入心跳包機制

微信的大規模使用真的會過多占用信令,影響通訊穩定嗎

https://blog.csdn.net/chrisnotfound/article/details/80111559

https://www.cnblogs.com/hukey/p/5481173.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/169354.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息