广告
返回顶部
首页 > 资讯 > 精选 >怎么在c#中利用socket实现一个心跳超时检测的功能
  • 730
分享到

怎么在c#中利用socket实现一个心跳超时检测的功能

2023-06-07 23:06:13 730人浏览 独家记忆
摘要

怎么在C#中利用Socket实现一个心跳超时检测的功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1 内存布局图假设socket3有新的数据到达,需要更新socket3所在的

怎么在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实现一个心跳超时检测的功能的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: 怎么在c#中利用socket实现一个心跳超时检测的功能

本文链接: https://www.lsjlt.com/news/250428.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在c#中利用socket实现一个心跳超时检测的功能
    怎么在c#中利用socket实现一个心跳超时检测的功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1 内存布局图假设socket3有新的数据到达,需要更新socket3所在的...
    99+
    2023-06-07
  • 怎么在python中利用opencv实现一个车道线检测功能
    这篇文章将为大家详细讲解有关怎么在python中利用opencv实现一个车道线检测功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。实现思路:canny边缘检测获取图中的边缘信息;2、霍夫变...
    99+
    2023-06-06
  • 怎么在Android中利用IntentUtil实现一个跳转功能
    本文章向大家介绍怎么在Android中利用IntentUtil实现一个跳转功能的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Android是什么Android是一种基于Linux内核的自由及开放源代码的操作系统...
    99+
    2023-05-30
    android intentutil
  • 怎么在Java中利用JUnit实现一个单元测试功能
    怎么在Java中利用JUnit实现一个单元测试功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。单元测试是编写测试代码,应该准确、快速地保证程序基本模块的正确性...
    99+
    2023-05-31
    java junit ava
  • 怎么在Android中利用CountDownTimer实现一个倒计时功能
    这篇文章主要介绍了怎么在Android中利用CountDownTimer实现一个倒计时功能,此处通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:Android是什么Android是一种基于Lin...
    99+
    2023-05-30
    android countdowntimer
  • C++中怎么利用Doxygen实现一个分享功能
    这篇文章给大家介绍C++中怎么利用Doxygen实现一个分享功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。用C++ Doxygen进行可自动文档化的代码注释,可从代码中提取注释生成帮助文档。在使用Doxygen时将...
    99+
    2023-06-17
  • 怎么在Android应用中利用View实现一个倒计时功能
    这篇文章将为大家详细讲解有关怎么在Android应用中利用View实现一个倒计时功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Android 自定义View实现倒计时需求:具体方法如下:...
    99+
    2023-05-31
    android roi view
  • 怎么在c#中利用WebRequest实现一个多文件上传功能
    本篇文章为大家展示了怎么在c#中利用WebRequest实现一个多文件上传功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。添加引用使用WebRequest需要添加引用System.Web,否则引入...
    99+
    2023-06-14
  • 怎么在SpringBoot中利用WebSocket实现一个群聊功能
    本篇文章为大家展示了怎么在SpringBoot中利用WebSocket实现一个群聊功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。消息群发创建新项目:添加依赖:<dependency>...
    99+
    2023-06-06
  • 怎么在Java中利用JDBC实现一个事务功能
    本文章向大家介绍怎么在Java中利用JDBC实现一个事务功能,主要包括怎么在Java中利用JDBC实现一个事务功能的使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Java是什么Java是一门面...
    99+
    2023-05-30
  • 怎么在Centos中利用文件实现一个swap功能
    怎么在Centos中利用文件实现一个swap功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。创建swap文件mkdir/var/swap#创建一个文件夹用于存放交换分区文件,...
    99+
    2023-06-10
  • 怎么在html5中利用canvas实现一个弹幕功能
    本篇文章为大家展示了怎么在html5中利用canvas实现一个弹幕功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。(function () {   ...
    99+
    2023-06-09
  • 怎么在Android中利用控件实现一个验证码倒计时功能
    这期内容当中小编将会给大家带来有关怎么在Android中利用控件实现一个验证码倒计时功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。使用方式<com.landptf.view.CountDownM...
    99+
    2023-05-31
    android roi
  • 怎么在Android应用中实现一个实时通信功能
    今天就跟大家聊聊有关怎么在Android应用中实现一个实时通信功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。实现原理就是将发送端,接收端分别放进一个线程去运行,然后利用线程通信类...
    99+
    2023-05-31
    android roi
  • 怎么在Android应用中实现一个跳转到主界面功能
    怎么在Android应用中实现一个跳转到主界面功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。//homeIntent intent= new Intent(Intent.A...
    99+
    2023-05-31
    android roi
  • 怎么在Android 中利用camera2 API 实现一个相机功能
    怎么在Android 中利用camera2 API 实现一个相机功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。流程因为 camera2 提供的接口比较多,虽然很灵活,但是也...
    99+
    2023-05-31
    android camera2 api roi
  • 怎么在Android中利用AlertDialog实现一个多选框功能
    怎么在Android中利用AlertDialog实现一个多选框功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在使用AlertDialog实现单选和多选对话框时,分别设置se...
    99+
    2023-05-31
    android alertdialog roi
  • 怎么在C#中使用MJPEG实现一个客户端功能
    怎么在C#中使用MJPEG实现一个客户端功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。环境:服务端MJPEG服务器使用的是手机的DroidCam,很方便的一个MJPEG服务...
    99+
    2023-06-06
  • 怎么在Android应用中利用View实现一个旋转功能
    本篇文章为大家展示了怎么在Android应用中利用View实现一个旋转功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。添加右侧旋转Bitmap turnBitmap =&nbs...
    99+
    2023-05-31
    android view roi
  • 在Android 开发中使用Activity怎么实现一个隐式跳转功能
    在Android 开发中使用Activity怎么实现一个隐式跳转功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。创建第二个activity就是创建一个class,继承自And...
    99+
    2023-05-31
    activity android roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作