日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java udp心跳机制_心跳包机制整理汇总

發布時間:2023/12/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java udp心跳机制_心跳包机制整理汇总 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【背景】

現需要實現這樣的功能:有多個客戶端連著同一個服務器。服務器和客戶端之間需要“互相”知道彼此的連接狀態。比如在某一時刻,服務器需要知道當前有多少個客戶端正在和其通信;某一個時刻,某個客戶端需要知道自己是否和服務器保持連接。如果在某一時刻,一個客戶端關閉了,服務端應能及時感覺到;同樣,如果服務端被關閉,所有的客戶端應能及時感覺到,并作出一些反應。

1.從程序的角度看待TCP掉線

TCP掉線的原因可能多種多樣、不一而足,比如,客人的電腦突然斷電、OS崩潰、路由器重啟、網線接觸不良、因為P2P下載軟件而導致網絡資源短缺、Internet網絡的不穩定等等,但是從程序的角度來說,我們可以總結為兩種情況:程序能立即感知的掉線和程序不能立即感知的掉線。

程序能立即感知的掉線:也就是說客戶端一掉線,服務器端的某個讀寫對應的TCP連接的線程就會拋出異常,這種情況相對容易處理。

程序不能立即感知的掉線:我們都知道,TCP連接的建立,需要經過三次握手;而TCP連接的斷開,需要經過四次揮手。掉線通常沒什么大不了的,掉就掉了唄,只要四次揮手順利完成后,服務器和客戶端分別做一些善后處理就可以。

麻煩的事情在于,連接在沒有機會完成4次揮手時已經斷開了(比如當客人的電腦系統死機,或客人電腦與服務器之間的某處物理網線斷開),而服務端以為客戶端還正常在線,而客戶端也自以為還正常在線。這種程序對現實狀態的錯誤判斷有可能引發諸多悲劇。比如,在此情況下,客戶端發一個指令給服務器,服務器因為沒有收到而一直處于等待指令的狀態;而客戶端了,以為服務器已經收到了,也就一直處于等待服務端回復的狀態。如果程序的其它部分需要依據當前的狀態來做后續的操作,那就可能會出問題,因為程序對當前連接狀態的判斷是錯誤的。

毫無疑問,這種對連接狀態錯誤的判斷所持續的時間越久,帶來可能的危害就越大。當然,如果我們不做任何額外的處理措施,服務器到最后也能感受到客戶端的掉線,但是,這個時間可能已經過去了幾分鐘甚至幾十分鐘。對于大多數應用來說,這是不可忍受的。 所以,針對這種不能立即感知掉線的情況,我們要做的補救措施,就是幫助程序盡快地獲知tcp連接已斷開的信息。

首先,我們可以在Socket上通過Socket.IOControl方法設置KeepAliveValues,來控制底層TCP的保活機制,比如,設定2秒鐘檢測一次,超過10秒檢測失敗時拋出異常。

byte[]?inOptionValues?=?FillKeepAliveStruct(1,?10000,?2000);

socket.IOControl(IOControlCode.KeepAliveValues,?inOptionValues,?null);

據我們的經驗,這種設定可以解決一部分問題,但是仍然會有一些連接在斷開后,遠遠超過10秒才被感知掉。所以,這個補救措施還是遠遠不夠的。我們還需要在應用層加入我們自己的TCP連接狀態檢測機制,這種機制就是通常所說的“心跳”。

2."心跳"機制

心跳機制的原理很簡單:客戶端每隔N秒向服務端發送一個心跳消息,服務端收到心跳消息后,回復同樣的心跳消息給客戶端。如果服務端或客戶端在M秒(M>N)內都沒有收到包括心跳消息在內的任何消息,即心跳超時,我們就認為目標TCP連接已經斷開了。

由于不同的應用程序對感知TCP掉線的靈敏度不一樣,所以,N和M的值就可以設定的不一樣。靈敏度要求越高,N和M就要越小;靈敏度要求越低,N和M就可以越大。而要求靈敏度越高,也是有代價的,那就是需要更頻繁地發送心跳消息,如果有幾千個連接同時頻繁地發送心跳消息,那么其所消耗的資源也是不能忽略的。

當然,網絡環境(如延遲的大小)的好壞,也對會對N和M的值的設定產生影響,比如,網絡延遲較大,那么N與M之間的差值也應該越大(比如,M是N的3倍)。否則,可能會產生誤判 -- 即TCP連接沒有斷開,只是因為網絡延遲大才及時沒收到心跳消息,我們卻認為連接已經斷開了。

ESFramework內置了心跳機制,當心跳超時時,服務端會觸發IUserManager的SomeOneTimeOuted事件,來通知我們的應用程序。

在服務器端,UserManager通過ESBasic.Threading.Application.HeartBeatChecker來對心跳進行檢測,而HeartBeatChecker的SurviveSpanInSecs屬性可以用于設置我們所描述的M值。

在客戶端,則通過ESPlus.Application.Basic.Passive.HeartBeater來向服務器定時發送心跳消息,而HeartBeater的DetectSpanInSecs屬性可以用于設置N值。

當我們在使用Rapid引擎時,Rapid引擎已經將心跳機制的組件為我們組裝好了。由于RapidServerEngine和RapidPassiveEngine沒有暴露出HeartBeatChecker和HeartBeater,所以,我們不能直接通過HeartBeatChecker和HeartBeater設定M和N的值,但是,RapidServerEngine和RapidPassiveEngine分別提供了HeartbeatTimeoutInSecs屬性和HeartBeatSpanInSecs屬性來間接地設定M和N。

3.必須關閉掉線的TCP連接

無論是普通掉線(立即感知)還是心跳超時掉線(非立即感知),都需要關閉對應的TCP連接以釋放系統資源。

ITcpServerEngine接口提供了CloseOneConnection方法以關閉目標連接。

///

/// 主動關閉連接,將觸發SomeOneDisconnected事件。

///

void CloseOneConnection(UserAddress adderss, DisconnectedType disconnectedType);

當普通掉線時,ITcpServerEngine會自動關閉了TCP連接;但是,當心跳超時掉線時,我們需要自己手動關閉對應的連接。幸運的是,ESPlus.Application.Basic空間下的組件會自動幫我們關閉超時掉線的連接。所以,使用Rapid引擎的我們也不用再自己手動關閉超時掉線的TCP連接了。

另外要提醒一點,當TCP連接超時掉線時,使用Rapid引擎的服務端會首先觸發IUserManager的SomeOneTimeOuted事件,接著再觸發IUserManager的SomeOneDisconnected事件(由于ESPlus調用CloseOneConnection方法時觸發)。

4.UDP與"心跳"

前面介紹的都是關于TCP的掉線的問題,下面我們看看UDP。

由于UDP是無連接的協議,所以,當我們在使用ESFramework的UDP引擎的時候,幾乎肯定是需要配備心跳機制的,使用心跳消息確認客戶端還在線,以保證服務端不會過早釋放對應的Session或長期保留已失效的Session。

ESFramework中的心跳機制相關的組件是與協議無關的,所以既可以用于TCP應用,也可用于UDP應用。

在ESFramework 開發手冊(04) -- 可靠的P2P 一文中介紹的P2P通道如果是基于UDP的,則ESPlus內部也啟動了心跳機制,以保證在基于UDP的P2P通道斷開時,ESPlus能盡快感知,并關閉對應的P2P通道。

5.關閉心跳機制

比如,在LAN中進行通信的分布式系統,由于網絡延遲和意外掉線的幾率微乎其微,所以,可以考慮關閉心跳機制。再比如,當我們斷點調試客戶端程序時,由于斷點時間太久,服務端會判斷為客戶端已經心跳超時掉線了,在這種情況下,也可以關閉心跳機制。那么如何關閉心跳機制了?可以這樣做:

將RapidPassiveEngine的HeartBeatSpanInSecs屬性設置為0。這樣客戶端就不會發送定時的心跳消息了。

將RapidServerEngine的HeartbeatTimeoutInSecs屬性設置為小于等于0。這表示服務端將不再做心跳超時檢查。

【思考】

看到這個需求,直觀上的反應就是在服務端維護一個在線列表。當服務端的監聽器監聽到一個連接,就把該連接對應的客戶端信息加入這個在線列表。這樣就完成了對上線狀況的記錄。但下一個問題是如何讓服務器知道客戶端的離線狀況呢?我們可能會想到,讓客戶端在關閉前發送一個消息到服務端,服務端收到消息后就把客戶端置為離線狀態。但是,在更多情況下,客戶端并不是這么“友好”地關閉的。應用程序崩潰、網絡連接被重置、機器死機等情況下,客戶端來不及發送“離線通知”給服務端就掛掉了。這時,需要有一套機制,能讓服務端和客戶端彼此對對方的在線狀態保持清醒。

【概念】

何謂“心跳”??心跳就是指“活著”的客戶端或服務端每隔一定的時間就互相發送接收一個消息,告訴對方自己“活著”。當客戶端或服務端超過一定的時間間隔尚未收到對方的“心跳”消息,就認為對方“死了”。這就是“心跳機制”的核心思想。

【設計實現】

在客戶端,除了?UI?外,需要三個線程在后臺工作。

1,自動連接的線程。該線程可以實現每隔指定時間就檢查一次連接狀態,如果發現當前是“離線”狀態,就自動發起向服務端的一次連接。

1?????????private?void?ThreadConnect()

2?????????{

3?????????????do

4?????????????{

5

6?????????????????if?(!_bConnected)

7?????????????????{

8?????????????????????_bConnected?=?_sender.Connect(_ip,?_port);

9

10?????????????????????if?(_bConnected)

11?????????????????????{

12

13?????????????????????????Thread?threadSendAndReceivePulseMessage?=?new?Thread(new?ThreadStart(ThreadSendAndReceivePulseMessage));

14?????????????????????????threadSendAndReceivePulseMessage.IsBackground?=?true;

15?????????????????????????threadSendAndReceivePulseMessage.Start();

16

17?????????????????????????Thread?threadCheckPulseCount?=?new?Thread(new?ThreadStart(ThreadCheckPulseCount));

18?????????????????????????threadCheckPulseCount.IsBackground?=?true;

19?????????????????????????threadCheckPulseCount.Start();

20

21?????????????????????????_pulseCount?=?0;

22

23?????????????????????????OnConnected(new?EventArgs());

24?????????????????????}

25

26?????????????????}

27?????????????????Thread.Sleep(_connectInterval);

28

29?????????????}

30?????????????while?(_bWorking?&&?_bAutoReconnect);

31?????????}

2,收發“心跳”消息的線程。該線程和服務端進行收發心跳消息。注意每收到服務器發來的消息,應將心跳計數器置零。心跳計數器的含義是已經隔了多少個心跳周期沒收到心跳消息了。

1?????????private?void?ThreadSendAndReceivePulseMessage()

2?????????{

3?????????????while?(_bWorking?&&?_bConnected)

4?????????????{

5

6?????????????????string?recv?=??_sender.Receive(64);

7

8

9?????????????????if?(recv?==?"PULSE")

10?????????????????{

11?????????????????????_pulseCount?=?0;

12

13?????????????????????_sender.Send("ALIVE");

14?????????????????}

15?????????????????else

16?????????????????{

17?????????????????????_bConnected?=?false;

18?????????????????????_sender.Close();

19

20?????????????????}

21?????????????????Thread.Sleep(10);

22?????????????}

23?????????}

3,檢查心跳計數器的值的線程。該線程每隔指定的時間間隔就檢查一次心跳計數器,當發現已經超過指定心跳周期(比如3次)未接收到心跳消息,就認為是離線了,則進行相應的處理。

1?????????private?void?ThreadCheckPulseCount()

2?????????{

3?????????????while?(_bWorking?&&?_bConnected)

4?????????????{

5?????????????????Thread.Sleep(_pulseInterval);

6

7?????????????????_pulseCount++;

8

9?????????????????if?(_pulseCount?>?_maxPulseCount)

10?????????????????{

11?????????????????????_bConnected?=?false;

12?????????????????????_sender.Close();

13?????????????????}

14

15?????????????????if?(!_bConnected)

16?????????????????{

17?????????????????????OnDisconnected(new?EventArgs());

18?????????????????}

19?????????????}

20?????????}

在服務端,設計思想類似,需要維護一個“在線列表”,并及時和客戶端通信,此處省略代碼。

總結

以上是生活随笔為你收集整理的java udp心跳机制_心跳包机制整理汇总的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。