1. 程式人生 > >為什麼基於TCP的應用需要心跳包(TCP keep-alive原理分析)

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

TCP keep-alive的三個引數

用man命令,可以檢視linux的tcp的引數:

man 7 tcp

其中keep-alive相關的引數有三個:

       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 before giving up and killing the connection if no response is obtained 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 TCP begins sending out keep-alive probes. Keep- alives are sent only when the
SO_KEEPALIVE socket option is enabled. The default value is 7200 seconds (2 hours). An idle connection is terminated after approximately an additional 11 minutes (9 probes an interval of 75 seconds apart) when keep-alive is enabled.

這些的預設配置值在/proc/sys/net/ipv4 目錄下可以找到。

可以直接用cat來檢視檔案的內容,就可以知道配置的值了。
也可以通過sysctl命令來檢視和修改:

# 查詢
cat /proc/sys/net/ipv4/tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_time
#修改
sysctl net.ipv4.tcp_keepalive_time=3600

上面三個是系統級的配置,在程式設計時有三個引數對應,可以覆蓋掉系統的配置:

TCP_KEEPCNT 覆蓋  tcp_keepalive_probes,預設9(次)
TCP_KEEPIDLE 覆蓋 tcp_keepalive_time,預設7200(秒)
TCP_KEEPINTVL 覆蓋 tcp_keepalive_intvl,預設75(秒)
 ```

## tcp keep-alive的本質
###TCP keep-alive probe
上面瞭解了tcp keep-alive的一些引數,下面來探究下其本質。

在遠端機器192.168.66.123上,用nc啟動一個TCP伺服器:
```bash
nc -l 9999




<div class="se-preview-section-delimiter"></div>

在本地機器上,用python建立一個socket去連線,並且用wireshark抓包分析

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 20)
s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 1)

s.connect(('192.168.66.123', 9999))

上面的程式,設定了TCP_KEEPIDLE為20,TCP_KEEPINTVL為1,系統預設的tcp_keepalive_probes是9。

當網路正常,不做干擾時,wireshark抓包的資料是這樣的(注意看第二列Time):

tcp-keepalive-good.png

可以看到,當3次握手完成之後,每隔20秒之後66.120傳送了一個TCP Keep-Alive的資料包,然後66.123迴應了一個TCP Keep-Alive ACK包。這個就是TCP keep-alive的實現原理了。

當傳送了第一個TCP Keep-Alive包之後,撥掉192.168.66.123的網線,然後資料包是這樣子的:
tcp-keepalive-bad.png

可以看到,當遠端伺服器192.168.66.123網路失去連線之後,本地機器(192.168.66.120)每隔一秒重發了9次tcp keep-alive probe,最終認為這個TCP連線已經失效,發了一個RST包給192.168.66.123。

在本地機器上,用python建立一個socket去連線,並且用wireshark抓包分析
```python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 20)
s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 1)

s.connect(('192.168.66.123', 9999))

上面的程式,設定了TCP_KEEPIDLE為20,TCP_KEEPINTVL為1,系統預設的tcp_keepalive_probes是9。

當網路正常,不做干擾時,wireshark抓包的資料是這樣的(注意看第二列Time):

tcp-keepalive-good.png

可以看到,當3次握手完成之後,每隔20秒之後66.120傳送了一個TCP Keep-Alive的資料包,然後66.123迴應了一個TCP Keep-Alive ACK包。這個就是TCP keep-alive的實現原理了。

當傳送了第一個TCP Keep-Alive包之後,撥掉192.168.66.123的網線,然後資料包是這樣子的:
tcp-keepalive-bad.png

可以看到,當遠端伺服器192.168.66.123網路失去連線之後,本地機器(192.168.66.120)每隔一秒重發了9次tcp keep-alive probe,最終認為這個TCP連線已經失效,發了一個RST包給192.168.66.123。

為什麼應用層需要heart beat/心跳包?

預設的tcp keep-alive超時時間太長

預設是7200秒,也就是2個小時。

socks proxy會讓tcp keep-alive失效

socks協議只管轉發TCP層具體的資料包,而不會轉發TCP協議內的實現細節的包(也做不到),參考socks_proxy

所以,一個應用如果使用了socks代理,那麼tcp keep-alive機制就失效了,所以應用要自己有心跳包。

socks proxy只是一個例子,真實的網路很複雜,可能會有各種原因讓tcp keep-alive失效。

行動網路需要信令保活

前兩年,微信信令事件很火,搜尋下“微信 信令”或者“行動網路 信令”可以查到很多相關文章。

總結

  • TCP keep-alive是通過在空閒時傳送TCP Keep-Alive資料包,然後對方迴應TCP Keep-Alive ACK來實現的。

  • 為什麼需要heart beat/心跳包?因為tcp keep-alive不能滿足人們的實時性的要求,就是這麼簡單。

相關推薦

為什麼基於TCP應用需要心跳TCP keep-alive原理分析

TCP keep-alive的三個引數 用man命令,可以檢視linux的tcp的引數: man 7 tcp 其中keep-alive相關的引數有三個: tcp_keepalive_intvl (integer; default:

心跳檢測不可檢測斷線

一般是用來判斷對方(裝置,程序或其它網元)是否正常動行,一般採用定時傳送簡單的通訊包,如果在指定時間段內未收到對方響應,則判斷對方已經當掉。用於檢測TCP的異常斷開。一般是用來判斷對方(裝置,程序或其它網元)是否正常動行,一般採用定時傳送簡單的通訊包,如果在指定時間段內未收到對方響應,則判斷對方已經當掉。用於

手機及電腦抓tcp,udp,http

1.軟體 下面兩款都是免費軟體。 1.1 fiddler 介面見圖1-1. 圖1-1 fiddler介面 1.2 wireshark 介面見圖1-2. 圖1-2 wireshark 介面 2. 電腦抓包 http包可以在fiddler裡面看。 http及tcp、udp包

JAVA網路程式設計實現基於TCP協議的時間服務向伺服器查詢當前時間

服務端程式: package doc_02_tcp.server; import java.io.PrintWriter; import java.net.InetAddress; import

TCP和UDP通信C#網絡編程 ---- 系列文章

xxxxx targe details 網絡編程 lan udp listen csdn href 文章系列目錄 C#網絡編程系列文章(一)之Socket實現異步TCP服務器 C#網絡編程系列文章(二)之Socket實現同步TCP服務器 C#網絡編程系列文章(三)之

為什麼保持長連線需要心跳

有一個問題不知道大家注意過沒有——為什麼socket客戶端在非正常斷開後,伺服器在很長一段時間內不會顯示客戶端斷開?沒有的話,大可以試試-。- 原因:        如果是正常終止客戶端程序,系統會

關於字符編碼,你所需要知道的ASCII,Unicode,Utf-8,GB2312…

tle cati http char 表示 編寫 編號 小端 調用 字符編碼的問題看似很小,經常被技術人員忽視,但是很容易導致一些莫名其妙的問題。這裏總結了一下字符編碼的一些普及性的知識,希望對大家有所幫助。 還是得從ASCII碼說起 說到字符編碼,不得不說ASCII碼的簡

基於web的網路考勤系統ajax+ligerUI+MVC+簡單工廠

序言       最近在整理自己的舊U盤的時候發現了幾個貢獻比較大對於整個系統比較熟悉的例子來給大家分享一下,因為該專案是17年大二的時候所作,稍有瑕疵請各位諒解。因為是鄙人第一個專案,所以不打算修改了,留作個紀念。 本系統框架利用了ligerUI的整體佈局與樣式,具

IDEA如何匯入的javaxservlet的api.jar檔案

1.在初次使用Intellij IDEA 編譯器的時候,當你使用Javax.servlet包時,(例如:javax.servlet.)你會發現編譯器無法編譯成功;將會報一系列有關javax.類的錯誤。 這是因為IDEA沒有匯入servlet-api

Go語言學習第八課-結構體與Go語言的面向物件

      接下來講解一下Go語言中的面向物件思想程式設計。在Go語言面向物件與其它面嚮物件語言有著很大的差別。首先Go語言的不存在繼承和多型,而且不存在建構函式。並且Go語言不採用class來實現類,而是採用結構體加指標實現。不得不說,這讓類的定義變得很複雜,但是又不失合理

最簡單的基於FFMPEG的視訊編碼器YUV編碼為H.264

                =====================================================最簡單的基於FFmpeg的視訊編碼器文章列表:=====================================================本文介紹一個最簡單的

Flask常用pip install -r x.txt

Package Version alembic 1.0.5 amqp 2.3.2 aniso8601 4.0.1 asn1crypto 0.24.0 billiard 3.5.0.5 blinker 1.4 celery 4.2.1 cffi 1.11.5 Click 7.0 cr

Django常用的pip install -r x.txt

Package Version aliyun-python-sdk-core-v3 2.11.0 aliyun-python-sdk-dysmsapi 1.0.0 aliyunsdkcore 1.0.3 asn1crypto 0.24.0 cffi 1.11.5 cryptogra

基於Tensorflow的Resnet程式實現CIFAR10準確率為91.5%

       在上一篇博文中我重寫了Tensorflow中的CNN的實現,對於CIFAR10的測試集的準確率為85%左右。在這個實現中,用到了2個卷積層和2個全連線層。具體的模型架構如下:        為了進一步提高準確率,我們可以採用一些更先進的模型架構,其中一種很

Linux下對已有專案快速打RPM只需編輯XML檔案

期間公司在做Migration的工作,經常遇到這樣的場景:需要對現有的二進位制第三方庫和標頭檔案打包成RPM包,以便臨時測試用或者第三方庫管理。但是,修改SPEC檔案並編寫Makefile是個鬱悶的事

android 自定義類似91遊,360應用內懸浮球不使用系統懸浮框

專案需要,製作類似360,UC類似遊戲內的懸浮球 1.開始使用的是系統的懸浮,新增系統許可權android.permission.SYSTEM_ALERT_WINDOW,獲取windowManager , 設定佈局引數,新增view來實現, 優點:處於系統最上層,一次新增,

基於Python輕度使用Chrome Headless谷歌瀏覽器無頭模式

簡單demo如下 # coding: utf-8 from selenium import webdriver chrome_options = webdriver.ChromeOptions()

基於winserver部署Apollo初次體驗附.net客戶端demo

前言 配置中心伴隨著這幾年分散式系統演變和微服務架構的興起,已經成為必不可少的需求之一。試下一下如果哪天公司的所有應用服務,從公司伺服器遷移到雲服務,成千上萬的配置,修改起來是多麼耗時費勁的事(我們公司就是……)。 配置中心主要有以下特點: 配置動態化 管理集中化 修改配置不需要重新發布配置

關於字元編碼,你所需要知道的ASCII,Unicode,Utf-8,GB2312…

總結: ascii碼佔用一個位元組 gb2312(gbk是其擴充套件)佔用兩個位元組 Unicode是一種編碼方式,utf-8,utf-16是其具體實現,決定每個字元位元組數量,uft-8為1-4,utf-16為2-4,Windows使用utf-16,Linux使用

iPhone手機下載應用軟體的區別itunes,i4和itools

1   下載應用軟體的時候的區別      iPhone手機用itunes和愛思下載應用軟體的時候,需要apple i和密碼      iPhone手機用itools下載應用軟體的時候,不需要apple ID和密碼 ,需要的時候只需要授權就可以了 2.在iPhone手機使用