心跳信號

辭彙

心跳信號是每隔一段時間向互聯的另一方發送一個很小的數據包,通過對方回復情況判斷互聯的雙方之間的通訊鏈路是否已經斷開的方法。

介紹


互聯的雙方中的一方,每隔固定的時間向另一方發送一個很小的數據包,另一方根據需要確定在收到數據包之後是否回復一個很小的數據包。每隔固定時間是很難達到的一個條件,實際情況是不超過某個時間間隔。

作用


心跳信號是為了確認一個事實——互聯的雙方在長時間沒有通訊的情況下是否都還在線,或者說存在於互聯的雙方之間的通訊鏈路是否已經斷開。而不是網上有些人所謂的“用來保持連接”,“用來維持長連接”。連接一旦建立,只能被異常或正常的斷開,而不會因為沒有數據傳輸而斷開的,所以沒有什麼長連接的概念,更不需要用發送數據的方式來保持連接。
有些防火牆或者電腦管理軟體會把超過一定時間沒有通訊的連接當作死連接,這些軟體會自動將死連接斷開或者請求用戶將死連接斷開。當有心跳時,不會被這類軟體當做死連接。看起來心跳信號像是保持了連接,這是只是心跳信號偶然間具有的作用。
長連接和短連接是應用層的概念。長連接表示當與某個目標創建應用層的連接后,目標不會因為沒有數據通訊而去斷開這個連接。短連接表示當需要與目標通信時創建連接通訊一結束立刻斷開,否則目標有可能也會因為長時間不通訊而將連接斷開,ftp伺服器就會。
ftp伺服器允許長連接屬性開啟后,ftp伺服器不會因為連接著的客戶端沒有長時間沒有上傳或者下載文件而關閉這個連接,對於ftp客戶端來說就是不需要採用短連接的方式上傳或者下載文件。

何時需要


顯然通過心跳信號的作用就可以知道,當應用層採用了長連接,並且會出現長時間不通訊的情況,並且雙方中至少有一方需要知道對方是否仍然在線或者數據鏈路是否仍然通暢時,才需要使用心跳信號。不管何種通訊協議,只要不是採用傳送數據時連接,傳送完畢立即斷開的方式那麼就是在應用層採用了長連接。
不管採用是基於連接的協議(如TCP),還是基於流的協議(如UDP),當在應用層採用了長連接方式時,都可能需要心跳信號。首先讓我們來看看這兩類協議的區別。
基於流的協議不需要建立連接,也不需要斷開,發送方向某個地址(IP加埠)發送數據,收取方從某個地址讀取數據。對於基於流的協議來說,發送方是否成功發送數據或者發送的數據是否被成功收取,發送方是不知道的;收取方沒有收到數據到底說明發送方沒有發送還是發送了但是丟失了,也是不知道的。其實串口通訊協議也算作是一種基於流的協議,雖然有一個打開串口的過程,其實這只是相當於請求獨佔一個埠,這也是串口不能重複被打開的原因。
基於連接的協議,在通訊前首先要建立連接,建立連接的過程包括一定步驟的雙向通訊;斷開連接也是一樣的,有心情的可以看一下TCP的通訊過程。基於連接的通訊協議每一次發送數據都是一個雙向的通訊過程,發送方發送數據,接收放收到數據后回復,如果沒收到回復重新發,重發0次或多次後會認為連接無故斷開了,報告發送失敗。顯然基於連接的協議能夠保證發送的數據被目標接收到了。數據包中對與應用來說有意義的部分數據是否正確是需要根據具體協議而定的,但是指明目的地址的包頭部分有錯誤肯定會導致重發或者發送失敗。
採用基於連接的協議通訊的雙方中的一方由於停電、當機、崩潰等原因沒有進行或者完成斷開連接的過程那麼另一方就不知道連接是否斷開了。對於基於連接的協議,一旦在應用層採用了長連接絕大多少情況下都需要心跳信號,除非程序不用長時間運行,不在乎死連接的性能損失。
對於基於流的協議,採用了長連接並且有一方需要確認和區分數據的來源地址(ip埠或者其它標識)且需要知道來源方或發送方是否還在線時才需要採用心跳信號。歸納起來就是如果一方需要知道另一方是否在線那麼一定需要心跳信號;如果一方需要知道另一方是否在線但是又不需要知道收到的數據來自何處,那麼程序肯定設計的有問題。僅僅區分數據來源是沒有必要為每一個來源都創建一個獨立的連接(其實不應該叫做連接,可以看做tcp、udp通訊採用的socket),更沒有必要採用心跳信號。收到數據之後就可以知道埠、IP,其它標識也可以添加到數據包里。

怎麼建立


傳送記錄類型的數據時
記錄類型的數據長短差異不是特別巨大,數據類型多樣,擁有一定的結構。發送這種類型的數據一般採用基於連接的協議(TCP),這樣可以保證每條數據都能送到目標。此時心跳信號應該算作通訊協議(這是應用層的協議)中的一種數據,和其它數據發送到同一個埠號。在協議設計過程中要考慮到用一種特別的標記將一條條的數據隔開,以防粘包。將心跳信號和其他數據的結構設計成一致的。將某條數據解析出來后通過其中的某個欄位來確認這條數據到底是心跳信號還是其他數據。
這種情況下心跳信號可以採用計時器每隔一段時間發送一次,而不用理會是否有其它類型的數據發送。接收方應該在至少經過2到3倍的約定時間沒有收到心跳信號時才認為連接斷開了。當然也可以有其它類型數據發送時,不發送心跳信號。這樣一來雙方的處理邏輯都複雜一些。不管採用何種方式,在的通訊協議都應該進行說明。
傳送文件或者視頻(數據)流時
傳送文件時一般採用基於連接的協議。如果採用基於流的協議,就需要自己處理某一個包是否送達目標的過程,而這個過程恰好是基於連接的協議的底層內容。
傳送視頻流和其它類型的數據流時一般採用基於流的協議。因為網路環境不至於差到每一幀數據中都有丟包。傳送視頻流時,丟了一包,帶來的影響也就是解碼出來的圖像花屏或者不能解碼;花屏沒什麼大不了,不能解碼直接丟棄也沒什麼影響。
傳送其它的數據流,比如從感測器不斷發回來的溫度、濕度等,從GPS接收機不斷發回來的定位信息。這些數據損壞了一幀,還有下一幀可以使用。所以也不在乎丟包。
對於這種流式數據不允許中間插入心跳數據。所以心跳數據的格式必須單獨設計。心跳的發送也有兩種方式。第一種,不管數據流是否在發送都每隔固定的時間將心跳數據發往不同於發數據流的埠。第二種,當發送數據流時不發送心跳信號。

特別說明


TCP已經包含了心跳信號。但是這個心跳信號受實現平台的限制比較多,並且默認是關閉的。如果開發伺服器程序盡量不要依賴這個功能。如果開發一些簡單的小應用時,並且可以預料到將來沒有平台遷移任務時才可以使用。