亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在c#中利用socket實現一個心跳超時檢測的功能

發布時間:2021-03-09 16:00:28 來源:億速云 閱讀:720 作者:Leah 欄目:開發技術

怎么在c#中利用socket實現一個心跳超時檢測的功能?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

1 內存布局圖

怎么在c#中利用socket實現一個心跳超時檢測的功能

假設socket3有新的數據到達,需要更新socket3所在的時間軸,處理邏輯如下:

怎么在c#中利用socket實現一個心跳超時檢測的功能

2 處理過程分析:

基本的處理思路就是增加時間軸概念。將socket按最后更新時間排序。因為時間是連續的,不可能將時間分割太細。首先將時間離散,比如屬于同一秒內的更新,被認為是屬于同一個時間點。離散的時間間隔稱為時間刻度,該刻度值可以根據具體情況調整。刻度值越小,超時計算越精確;但是計算量增大。如果時間刻度為10毫秒,則一秒的時間長度被劃分為100份。所以需要對更新時間做規整,代碼如下:

DateTime CreateNow()
 {
  DateTime now = DateTime.Now;
  int m = 0; 
  if(now.Millisecond != 0)
  {
  if(_minimumScaleOfMillisecond == 1000)
  {
   now = now.AddSeconds(1); //尾數加1,確保超時值大于 給定的值
  }
  else
  {
   //如果now.Millisecond為16毫秒,精確度為10毫秒。則轉換后為20毫秒
   m = now.Millisecond - now.Millisecond % _minimumScaleOfMillisecond + _minimumScaleOfMillisecond;
   if(m>=1000)
   {
   m -= 1000;
   now = now.AddSeconds(1);
   }
  }
  }
  return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second,m);
 }

屬于同一個時間刻度的socket,被放入在一個哈希表中(見圖中Group)。存放socket的類如下:

class SameTimeKeyGroup<T>
 {
 DateTime _timeStamp;
 public DateTime TimeStamp => _timeStamp;
 public SameTimeKeyGroup(DateTime time)
 {
  _timeStamp = time;
 }
 public HashSet<T> KeyGroup { get; set; } = new HashSet<T>();

 public bool ContainKey(T key)
 {
  return KeyGroup.Contains(key);
 }

 internal void AddKey(T key)
 {
  KeyGroup.Add(key);
 }
 internal bool RemoveKey(T key)
 {
  return KeyGroup.Remove(key);
 }
 }

 定義一個List表示時間軸:

List<SameTimeKeyGroup<T>> _listTimeScale = new List<SameTimeKeyGroup<T>>();

 在_listTimeScale 前端的時間較舊,所以鏈表前端就是有可能超時的socket。

當有socket需要更新時,需要快速知道socket所在的group。這樣才能將socket從舊的group移走,再添加到新的group中。需要新增一個鏈表:

 Dictionary<T, SameTimeKeyGroup<T>> _socketToSameTimeKeyGroup = new Dictionary<T, SameTimeKeyGroup<T>>();

2.1 當socket有新的數據到達時,處理步驟:

  • 查找socket的上一個群組。如果該群組對應的時刻和當前時刻相同(時間都已經離散,才有可能相同),無需更新時間軸。

  • 從舊的群組刪除,增加到新的群組。

public void UpdateTime(T key)
 {
  DateTime now = CreateNow();
  //是否已存在,從上一個時間群組刪除
  if (_socketToSameTimeKeyGroup.ContainsKey(key))
  {
  SameTimeKeyGroup<T> group = _socketToSameTimeKeyGroup[key];
  if (group.ContainKey(key))
  {
   if (group.TimeStamp == now) //同一時間更新,無需移動
   {
   return;
   }
   else
   {
   group.RemoveKey(key);
   _socketToSameTimeKeyGroup.Remove(key);
   }
  }
  }

  //從超時組 刪除
  _timeoutSocketGroup.Remove(key);

  //加入到新組
  SameTimeKeyGroup<T> groupFromScaleList = GetOrCreateSocketGroup(now, out bool newCreate);
  groupFromScaleList.AddKey(key);

  _socketToSameTimeKeyGroup.Add(key, groupFromScaleList);

  if (newCreate)
  {
  AdjustTimeout();
  }
 }

2.2 獲取超時的socket

 時間軸從舊到新,對比群組的時間與超時時刻。就是鏈表_listTimeScale,從0開始查找。

/// <summary>
 ///timeLimit 值為超時時刻限制 
 ///比如DateTime.Now.AddMilliseconds(-1000);表示 返回一秒鐘以前的數據
 /// </summary>
 /// <param name="timeLimit">該時間以前的socket會被返回</param>
 /// <returns></returns>
 public List<T> GetTimeoutValue(DateTime timeLimit, bool remove = true)
 {
  if((DateTime.Now - timeLimit) > _maxSpan )
  {
  Debug.Write("GetTimeoutSocket timeLimit 參數有誤!");
  }

  //從超時組 讀取
  List<T> result = new List<T>();
  foreach(T key in _timeoutSocketGroup)
  {
  _timeoutSocketGroup.Add(key);
  }

  if(remove)
  {
  _timeoutSocketGroup.Clear();
  }

  while (_listTimeScale.Count > 0)
  {
  //時間軸從舊到新,查找對比
  SameTimeKeyGroup<T> group = _listTimeScale[0];
  if(timeLimit >= group.TimeStamp)
  {
   foreach (T key in group.KeyGroup)
   {
   result.Add(key);
   if (remove)
   {
    _socketToSameTimeKeyGroup.Remove(key);
   }
   }

   if(remove)
   {
   _listTimeScale.RemoveAt(0);
   }
  }
  else
  {
   break;
  }
  }

  return result;
 }

3 使用舉例

//創建變量。最大超時時間為600秒,時間刻度為1秒
TimeSpanManage<Socket> _deviceActiveManage = TimeSpanManage<Socket>.Create(TimeSpan.FromSeconds(600), 1000);

//當有數據到達時,調用更新函數 
_deviceActiveManage.UpdateTime(socket);

//需要在線程或定時器中,每隔一段時間調用,找出超時的socket
//找出超時時間超過600秒的socket。
foreach (Socket socket in _deviceActiveManage.GetTimeoutValue(DateTime.Now.AddSeconds(-600)))
{
 socket.Close();
}

4 完整代碼

/// <summary>
 /// 超時時間 時間間隔處理
 /// </summary>
 class TimeSpanManage<T>
 {
 TimeSpan _maxSpan;
 int _minimumScaleOfMillisecond;
 int _scaleCount;

 List<SameTimeKeyGroup<T>> _listTimeScale = new List<SameTimeKeyGroup<T>>();
 private TimeSpanManage()
 {
 }

 /// <summary>
 ///
 /// </summary>
 /// <param name="maxSpan">最大時間時間</param>
 /// <param name="minimumScaleOfMillisecond">最小刻度(毫秒)</param>
 /// <returns></returns>
 public static TimeSpanManage<T> Create(TimeSpan maxSpan, int minimumScaleOfMillisecond)
 {
  if (minimumScaleOfMillisecond <= 0)
  throw new Exception("minimumScaleOfMillisecond 小于0");
  if (minimumScaleOfMillisecond > 1000)
  throw new Exception("minimumScaleOfMillisecond 不能大于1000");

  if (maxSpan.TotalMilliseconds <= 0)
  throw new Exception("maxSpan.TotalMilliseconds 小于0");

  TimeSpanManage<T> result = new TimeSpanManage<T>();
  result._maxSpan = maxSpan;
  result._minimumScaleOfMillisecond = minimumScaleOfMillisecond;

  result._scaleCount = (int)(maxSpan.TotalMilliseconds / minimumScaleOfMillisecond);
  result._scaleCount++;
  return result;
 }

 Dictionary<T, SameTimeKeyGroup<T>> _socketToSameTimeKeyGroup = new Dictionary<T, SameTimeKeyGroup<T>>();
 public void UpdateTime(T key)
 {
  DateTime now = CreateNow();
  //是否已存在,從上一個時間群組刪除
  if (_socketToSameTimeKeyGroup.ContainsKey(key))
  {
  SameTimeKeyGroup<T> group = _socketToSameTimeKeyGroup[key];
  if (group.ContainKey(key))
  {
   if (group.TimeStamp == now) //同一時間更新,無需移動
   {
   return;
   }
   else
   {
   group.RemoveKey(key);
   _socketToSameTimeKeyGroup.Remove(key);
   }
  }
  }

  //從超時組 刪除
  _timeoutSocketGroup.Remove(key);

  //加入到新組
  SameTimeKeyGroup<T> groupFromScaleList = GetOrCreateSocketGroup(now, out bool newCreate);
  groupFromScaleList.AddKey(key);

  _socketToSameTimeKeyGroup.Add(key, groupFromScaleList);

  if (newCreate)
  {
  AdjustTimeout();
  }
 }

 public bool RemoveSocket(T key)
 {
  bool result = false;
  if (_socketToSameTimeKeyGroup.ContainsKey(key))
  {
  SameTimeKeyGroup<T> group = _socketToSameTimeKeyGroup[key];
  result = group.RemoveKey(key);

  _socketToSameTimeKeyGroup.Remove(key);
  }

  //從超時組 刪除
  bool result2 = _timeoutSocketGroup.Remove(key);
  return result || result2;
 }

 /// <summary>
 ///timeLimit 值為超時時刻限制
 ///比如DateTime.Now.AddMilliseconds(-1000);表示 返回一秒鐘以前的數據
 /// </summary>
 /// <param name="timeLimit">該時間以前的socket會被返回</param>
 /// <returns></returns>
 public List<T> GetTimeoutValue(DateTime timeLimit, bool remove = true)
 {
  if((DateTime.Now - timeLimit) > _maxSpan )
  {
  Debug.Write("GetTimeoutSocket timeLimit 參數有誤!");
  }

  //從超時組 讀取
  List<T> result = new List<T>();
  foreach(T key in _timeoutSocketGroup)
  {
  _timeoutSocketGroup.Add(key);
  }

  if(remove)
  {
  _timeoutSocketGroup.Clear();
  }

  while (_listTimeScale.Count > 0)
  {
  //時間軸從舊到新,查找對比
  SameTimeKeyGroup<T> group = _listTimeScale[0];
  if(timeLimit >= group.TimeStamp)
  {
   foreach (T key in group.KeyGroup)
   {
   result.Add(key);
   if (remove)
   {
    _socketToSameTimeKeyGroup.Remove(key);
   }
   }

   if(remove)
   {
   _listTimeScale.RemoveAt(0);
   }
  }
  else
  {
   break;
  }
  }

  return result;
 }

 HashSet<T> _timeoutSocketGroup = new HashSet<T>();
 private void AdjustTimeout()
 {
  while (_listTimeScale.Count > _scaleCount)
  {
  SameTimeKeyGroup<T> group = _listTimeScale[0];
  foreach (T key in group.KeyGroup)
  {
   _timeoutSocketGroup.Add(key);
  }

  _listTimeScale.RemoveAt(0);
  }
 }

 private SameTimeKeyGroup<T> GetOrCreateSocketGroup(DateTime now, out bool newCreate)
 {
  if (_listTimeScale.Count == 0)
  {
  newCreate = true;
  SameTimeKeyGroup<T> result = new SameTimeKeyGroup<T>(now);
  _listTimeScale.Add(result);
  return result;
  }
  else
  {
  SameTimeKeyGroup<T> lastGroup = _listTimeScale[_listTimeScale.Count - 1];
  if (lastGroup.TimeStamp == now)
  {
   newCreate = false;
   return lastGroup;
  }

  newCreate = true;
  SameTimeKeyGroup<T> result = new SameTimeKeyGroup<T>(now);
  _listTimeScale.Add(result);
  return result;
  }
 }

 DateTime CreateNow()
 {
  DateTime now = DateTime.Now;
  int m = 0;
  if(now.Millisecond != 0)
  {
  if(_minimumScaleOfMillisecond == 1000)
  {
   now = now.AddSeconds(1); //尾數加1,確保超時值大于 給定的值
  }
  else
  {
   //如果now.Millisecond為16毫秒,精確度為10毫秒。則轉換后為20毫秒
   m = now.Millisecond - now.Millisecond % _minimumScaleOfMillisecond + _minimumScaleOfMillisecond;
   if(m>=1000)
   {
   m -= 1000;
   now = now.AddSeconds(1);
   }
  }
  }
  return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second,m);
 }
 }

 class SameTimeKeyGroup<T>
 {
 DateTime _timeStamp;
 public DateTime TimeStamp => _timeStamp;
 public SameTimeKeyGroup(DateTime time)
 {
  _timeStamp = time;
 }
 public HashSet<T> KeyGroup { get; set; } = new HashSet<T>();

 public bool ContainKey(T key)
 {
  return KeyGroup.Contains(key);
 }

 internal void AddKey(T key)
 {
  KeyGroup.Add(key);
 }
 internal bool RemoveKey(T key)
 {
  return KeyGroup.Remove(key);
 }
 }

看完上述內容,你們掌握怎么在c#中利用socket實現一個心跳超時檢測的功能的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

吉水县| 修武县| 焦作市| 海淀区| 北宁市| 衡水市| 英吉沙县| 房产| 德庆县| 西充县| 乐清市| 永济市| 乌恰县| 宜都市| 保亭| 横峰县| 财经| 鄢陵县| 武功县| 黄冈市| 礼泉县| 唐山市| 肇州县| 邵武市| 宜城市| 英德市| 茌平县| 百色市| 盐津县| 河池市| 桂林市| 九江县| 尚志市| 宿松县| 廊坊市| 买车| 丰台区| 金秀| 新津县| 金沙县| 林州市|