提及網絡應用編程,想到最多的就是聊天類的軟件。固然,在這類軟件中,通常都會有一個用戶掉線檢測功能。今天咱們就經過使用自定義的HeartBeat方式來檢測用戶的掉線狀況。編程
心跳包實現思路服務器
咱們採用的思路是:客戶端鏈接上服務端之後,服務端維護一個在線用戶字典,客戶端每隔一段時間,向服務器發送一個心跳包,服務器接收到包之後,字典數據的值都會更新爲0;一旦服務端超過規定時間沒有接收到客戶端發來的包,字典數據將會遞增長一,當字典數據的值累計大於等於三,則視爲掉線。網絡
代碼邏輯less
客戶端每隔一段時間,發送一個心跳包:ide
#region 心跳Timer計數事件 private void heartbeatTimer_Tick(object sender, EventArgs e) { currentCount++; if (currentCount == heartbeatCount) { txtMessage.Append("開始發送心跳包"); MessageEntity entity = new MessageEntity(); entity.MessageType = MessagePicks.Heartbeat; entity.NickName = loginName; WriteToStream(entity); currentCount = 0; } } #endregion
在服務端,會開啓一個定時器,定時將userOnLineCounter中的值遞增長一。若是此時收到客戶端的心跳包,則將userOnLineCounter中的值重置。spa
private void heartbeatTimer_Tick(object sender, EventArgs e) { tickCountInStep++; if (tickCountInStep == tickCount) { if (userCollection.Count > 0) { //計數器自動遞增 expiryCountInStep++; foreach (User user in userLists) { userOnLineCounter[user]++; } //連續監測三次以後,開始監測集合中的掉線狀況 if (expiryCountInStep == expiryCount) { //尋找集合中「掉線」的用戶 var disconnectedUsers = userOnLineCounter.Where(p => p.Value >= 3).ToList(); foreach (var disconnectedUser in disconnectedUsers) { txtLog.Append("用戶" + disconnectedUser.Key.name + "掉線!"); //刪除集合中被視爲掉線的用戶 userLists.Remove(disconnectedUser.Key); userOnLineCounter.Remove(disconnectedUser.Key); //開始廣播發送掉線用戶 MessageEntity entity = new MessageEntity(); entity.MessageType = MessagePicks.OffLine; EndPoint curOfflineUserEP = disconnectedUser.Key.client.Client.RemoteEndPoint; string userName = disconnectedUser.Key.name; entity.MessageContentEx.Add(curOfflineUserEP, userName); ObjectInversion inversion = new ObjectInversion(); byte[] byteArr = inversion.SerializeTo((object)entity); try { foreach (User user in userLists) { user.writer.Write(byteArr); user.writer.Flush(); } } catch { } } expiryCountInStep = 0; } } tickCountInStep = 0; } } }
收到客戶端心跳包,自動重置計數器。3d
case MessagePicks.Heartbeat: txtLog.Append("收到客戶端" + entity.NickName + "的心跳回應包."); if (userOnLineCounter.ContainsKey(user)) userOnLineCounter[user] = 0; else userOnLineCounter.Add(user, 0); break;
效果圖code
(圖1:三個客戶端鏈接一個服務器)blog
(圖2:用戶「上善若水」掉線)事件
(圖3:用戶「古道熱腸」掉線)
程序暫時還未徹底完成,有須要的能夠參考下。固然也期待你們的各類思路。
代碼很醜,指望你們指點下重構的方法。
源碼下載
=====================2014年9月24日重構版本=======================
用戶實體內部經過維護一個timer計數器,實現心跳檢測,心跳超時功能。