關于socket長連接的心跳包

原文:http://m.blog.csdn.net/article/details?id=37883567

TCP的socket本身就是長連接的,那么為什么還要心跳包呢?

在smack里有個30s發(fā)送一個空消息的線程,同樣關于心跳包(keepalive)

據(jù)網(wǎng)絡搜索到的資料解釋如下

內網(wǎng)機器如果不主動向外發(fā)起連接,外網(wǎng)機沒法直連內網(wǎng)的,這也是內網(wǎng)機安全的原因之一,又因為路由器會把這個關系記錄下來,但是過一段時間這個記錄可能會丟失 ,所有每一個客戶端每隔一定時間就會向服務器發(fā)送消息,以保證服務器可以隨時找到你,這東西被稱為心跳包。

理論上說,這個連接是一直保持連接的,但是實際情況中,如果中間節(jié)點出現(xiàn)什么故障是難以知道的。更要命的是,有的節(jié)點(防火墻)會自動把一定時間之內沒有數(shù)據(jù)交互的連接給斷掉。在這個時候,就需要我們的心跳包了,用于維持長連接,保活。在獲知了斷線之后,服務器邏輯可能需要做一些事情,比如斷線后的數(shù)據(jù)清理,重新連接……當然,這個自然是要由邏輯層根據(jù)需求去做了??偟膩碚f,心跳包主要也就是用于長連接的?;詈蛿嗑€處理。一般的應用下,判定時間在30-40秒比較不錯。如果實在要求高,那就在6-9秒。

如果不主動關閉socket的話,系統(tǒng)不會自動關閉的,除非當前進程掛掉了,操作系統(tǒng)把占用的socket回收了才會關閉。為什么需要心跳連接主要是判斷當前連接是否是有效的、可被使用的。在實際應用中假設一段時間沒有數(shù)據(jù)傳輸時候理論上說應該連接是沒有問題的,但是網(wǎng)絡復雜,中途出現(xiàn)問題也是常見的,網(wǎng)線被掐斷了、對方進程掛掉了、頻繁丟包等,這時候TCP連接是不可使用的,但是對于應用層并不知道,如果需知道網(wǎng)絡情況則要很復雜的超時進行了解,TCP從底層就實現(xiàn)了這樣的功能。心跳機制是TCP在一段時間間隔后發(fā)送確認連接端是否還存在,如果存在的話就會回傳一個包確定網(wǎng)絡有效,如果心跳包有問題,則通知上層應用當前網(wǎng)絡有問題了。

這取決于你的server端的超時配置, 每個socket連接都是長連接,它是一個相當占用系統(tǒng)資源的通信管道, 如果這個長連接什么事也沒干硬是要占著資源,則server端可以選擇關閉這個連接,以省下資源讓更多的用戶連接進來。

所以,即便客戶端的是采用死循環(huán)while(true)方式連到服務端,對于特定的客戶端和服務端類型來說也需要一定時間間隔的心跳(告訴服務端,我還活著,雖然我沒干活也沒說話,但別把我關了)

以前開發(fā)手機游戲時,索愛有一款手機有強制要求,客戶端如果超過三分鐘無消息發(fā)向網(wǎng)絡服務端,則會在客戶端自動地強制把socket關斷。因為socket長連接相對于手機這樣資源少的設備來說是寶貴的資源。? (這個強制是指客戶端系統(tǒng)自動關的,不是我們代碼close的)

在TCP的機制里面,本身是存在有心跳包的機制的,也就是TCP的選項:SO_KEEPALIVE。系統(tǒng)默認是設置的2小時的心跳頻率。但是它檢查不到機器斷電、網(wǎng)線拔出、防火墻這些斷線。而且邏輯層處理斷線可能也不是那么好處理。一般,如果只是用于?;钸€是可以的。

心跳包一般來說都是在邏輯層發(fā)送空的echo包來實現(xiàn)的。下一個定時器,在一定時間間隔下發(fā)送一個空包給客戶端,然后客戶端反饋一個同樣的空包回來,服務器如果在一定時間內收不到客戶端發(fā)送過來的反饋包,那就只有認定說掉線了。

其實,要判定掉線,只需要send或者recv一下,如果結果為零,則為掉線。

另外記一個CSDN上早些年的問題:

QQ等程序聊天,雙方是否使用SOCKET通信?應該不會都是通過服務器吧,那樣服務器負擔得多大?。?/p>

如果是SOCKET,那么多的好友,一下子得建立多少個?。窟€得考慮上線下線隱身等亂七八糟的問題。

請高手幫忙指點一下這種復雜程序的結構,謝謝。

我還是很有發(fā)言權的呀,我畢業(yè)設計就是寫的這個(不過當時用的是vc寫的,帶文件傳輸?shù)模〡hl_ghost

我來說下我的思路吧:

1.如何知道誰在線?

Server維護一個list就ok了(存所有人的ip,名字,在線等)

2.如何讓服務器隨時能找到你?

前提:內網(wǎng)機器如果不主動向外發(fā)起連接,外網(wǎng)機沒法直連內網(wǎng)的,這也是內網(wǎng)機安全的原因之一吧,又因為路由器會把這個關系記錄下來,但是過一段時間這個記錄可能會丟失?,所有每一個客戶端 ? ?每隔一定時間就會向服務器發(fā)送消息,以保證服務器可以隨時找到你,這東西被稱為心跳包。

3.如何跨內網(wǎng)直連

Nat打洞(難):

我簡單說下原理,有兩個客戶端A,B?,當然必須有Server啦(他可以隨時連接A,B)

當A想連B時,A就回從Server那要B的ip,然后與B建立連接(第一次不能成功的,因為看紅字)。

這時A告訴Server,我找不到B,你替我告訴他一聲,我想與它連接,服務器就告訴B,你給A下一個請?zhí)˙發(fā)請求向A)!

這時A再向B發(fā)起連接就可以成功了(以后就不用server幫忙了)。

4.如何保證數(shù)據(jù)的可靠性(難)

滑動窗口協(xié)議,這個一句話兩句說不清楚啦,自己google下。

5是否在線。

我的設計是每隔40秒客戶端把Server中存自己的信息中的在線改為真,而服務器每過45秒就檢查這個在線變量是否為真,真的話把他改成假,如果假的話就說明這個人在45秒沒有向Server報到=>他網(wǎng)絡出現(xiàn)異常了,掉線了,向其它人發(fā)這個人的掉線通知。(這么設計原因在于當用戶網(wǎng)斷了沒有發(fā)下線通知,我們也能知道他不在線了)

6文件傳輸(難)

把文件讀到buf里,然后每次發(fā)1024b(當收到接收方確認后再發(fā)下一個1024b)。

參考文章

http://www.cppblog.com/tx7do/archive/2009/11/09/100513.html

http://bbs.csdn.net/topics/270063434

http://blog.csdn.net/klarclm/article/details/7784265

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容