美文网首页
一个简易的心跳包 C# Socket (上)

一个简易的心跳包 C# Socket (上)

作者: 懒_开果 | 来源:发表于2019-09-27 17:11 被阅读0次

    上篇 讲讲 代码 下篇就是讲下示例上面的使用了

    先来看看代码吧:

    1.KGHeartBeat 单个心跳包的数据类

    using System;
    
    
    
    namespace KGSocket.Tool
    {
        public class KGHeartBeat
        {
    
            //保存上一次心跳的时间
            protected long lastHeartTime;
    
            //超时次数
            public int Lostcount;
    
            //心跳包最大超时多少次
            public int MaxLostcount;
    
            //超时多久算一次
            public double MaxLostTime;
    
            //计算时间差的
            public long NowTimeSpan => Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);
    
            /// <summary>
            /// 检查心跳包延时
            /// </summary>
            public virtual void CheckHeat()
            {
                if (Math.Abs(lastHeartTime - this.NowTimeSpan) > MaxLostTime)
                {
                   
                    lastHeartTime = this.NowTimeSpan;
                    Lostcount++;
                }
            }
    
    
            /// <summary>
            /// 更新心跳包
            /// </summary>
            public virtual void UpdateHeat()
            {
                lastHeartTime = this.NowTimeSpan;
                Lostcount = 0;
            }
    
            public virtual T InitMax<T>(double maxlosttime = 2, int maxlost = 3) where T: KGHeartBeat
            {
                MaxLostTime = maxlosttime;
                MaxLostcount = maxlost;
                //第一次赋值肯定要刷新
                lastHeartTime = this.NowTimeSpan;
                return this as T;
            }
    
            public virtual void InitMax(double maxlosttime = 2, int maxlost = 3) 
            {
                MaxLostTime = maxlosttime;
                MaxLostcount = maxlost;
                //第一次赋值肯定要刷新
                lastHeartTime = this.NowTimeSpan;
            }
    
        }
    }
    
    

    貌似 都注释上了没啥好说的, NowTimeSpan => Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 这个就是一个只读的写法,每次读取都会读现在的时间与默认的时间差距秒,从而去计算心跳包的秒数
    InitMax()就是初始化上限数值 超时次数 超时上限
    UpdateHeat()就是更新心跳包的 重新赋值当前与默认时间的差距秒数, 如果过段时间不更新不更新当前持有的秒数也不会更新 在CheckHeat()检测超过限定的超时时间MaxLostTime 就是增加一次Lostcount超时次数

    2.KGHeartBeatManage<T,R>心跳包的管理类

    using System;
    using System.Collections.Generic;
    
    
    
    
    namespace KGSocket.Tool
    {
        public class KGHeartBeatManage<T, R> : IDisposable where R : KGHeartBeat, new()
        {
    
    
            //主定时器
            public System.Timers.Timer Checktimer;
            public System.Timers.Timer Sendtimer;
    
            private readonly object mlock = new object();
    
    
            //发送心跳包事件
            public event Action<T> SendHearEvent;
    
            //心跳包超时事件
            public event Action<T> ConnectLostEvent;
    
            //每个会话对应一个心跳KGHeartBeat
            private Dictionary<T, R> connectDic = new Dictionary<T, R>();
    
            public Dictionary<T, R> ConnectDic { get => connectDic; protected set => connectDic = value; }
    
    
    
            public virtual KGHeartBeatManage<T, R> InitTimerEvent(Action<T> sendHearEvent, Action<T> connectLostEvent, double Checkinterval = 1000, double Sendinterval = 1000)
            {
                //这里是赋值每过多少秒执行一次事件
                Checktimer = new System.Timers.Timer(Checkinterval);
                Sendtimer = new System.Timers.Timer(Sendinterval);
    
    
                SendHearEvent = sendHearEvent;
                ConnectLostEvent = connectLostEvent;
    
                //定时执行事件
                Checktimer.Elapsed += (v, f) =>
                {
                    //遍历每个会话回调一次检查心跳包
                   
                        CheckHeartBeat();
                    
    
                };
    
                //定时执行事件
                Sendtimer.Elapsed += (v, f) =>
                {
                    //遍历每个会话回调一次发送心跳包
                    lock (mlock)
                    {
                        SendHeartBeat();
                    }
    
                };
    
                return this;
            }
    
            public virtual KGHeartBeatManage<T, R> StartTimer()
            {
                Checktimer.Start();
                Sendtimer.Start();
                return this;
            }
    
            public virtual KGHeartBeatManage<T, R> StopTimer()
            {
                Checktimer.Stop();
                Sendtimer.Stop();
                return this;
            }
    
    
            /// <summary>
            /// 发送心跳包
            /// </summary>
            public virtual void SendHeartBeat()
            {
                lock (mlock)
                {
                    if (ConnectDic.Count > 0&& SendHearEvent!=null)
                    {
                        List<T> RemoveList = new List<T>();
                        foreach (KeyValuePair<T, R> item in ConnectDic)
                        {
                            SendHearEvent?.Invoke(item.Key);
    
                        }
                    }
                }
            }
    
            /// <summary>
            /// 检查心跳包
            /// </summary>
            public virtual void CheckHeartBeat()
            {
                lock (mlock)
                {
                    if (ConnectDic.Count > 0)
                    {
                        List<T> RemoveList = new List<T>();
                        foreach (KeyValuePair<T, R> item in ConnectDic)
                        {
                           
    
                            //检查 心跳包超时 如果超时满次数就移除并回调事件
                            item.Value.CheckHeat();
                            if (item.Value.Lostcount >= item.Value.MaxLostcount)
                            {
                                RemoveList.Add(item.Key);
    
                            }
                            RemoveList.ForEach(remove =>
                            {
                                ConnectLostEvent(remove);
                                ConnectDic.Remove(remove);
                            });
                        }
                    }
                }
            }
    
            /// <summary>
            /// 添加存储新的心跳包
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="heart"></param>
            /// <param name="maxlosttime"></param>
            /// <param name="maxlost"></param>
            public  KGHeartBeatManage<T, R> AddConnectDic(T obj,  double maxlosttime = 2, int maxlost = 3)
            {
                R heartBeat= new R().InitMax<R>(maxlosttime,maxlost);
    
                lock (mlock)
                {
                    ConnectDic.Add(obj, heartBeat);
                }
    
                return this;
            }
    
    
            public KGHeartBeatManage<T, R> RemoveConnectDic(T obj)
            {
                lock (mlock)
                {
                    ConnectDic.Remove(obj);
                }
    
                return this;
            }
    
            /// <summary>
            /// 更新指定会话对应的心跳包
            /// </summary>
            /// <param name="obj"></param>
            public void UpdateOneHeat(T obj)
            {
                lock (mlock)
                {
                    ConnectDic[obj].UpdateHeat();
                }
            }
    
            public void Dispose()
            {
                Checktimer.Dispose();
                Sendtimer.Dispose();
            }
    
        }
    }
    
    
    

    KGHeartBeatManage<T,R>:IDisposable where R:KGHeartBeat 这里的T就是你们定义的每个会话管理类,R就是指定要继承KGHeartBeat 的

    初始化事件 InitTimerEvent(第一个委托就是发送事件,第二个委托就是 每个心跳包如果超时就会回调回来,每隔多少毫秒触发一次检测,每隔多少毫秒发送心跳包)
    然后StartTimer()就可以开始触发了
    这边定时器那里加了个每次都会检测ConnectDic字典里面储存的心跳包,如果超过最大上限超时次数就会回调 KGHeartBeatManage里面的第二个委托,告诉他这个连接已经超时,

    AddConnectDic(对应的会话管理类,指定超时时间,超时次数)这里会创建出对应的KGHeartBeat数据里存在字典里面,每个会话管理对应一个心跳包数据
    RemoveConnectDic(T obj) 这里是移除字典里面 该会话管理对应的心跳包

    因为会有多线程触发的问题这里用了lock互斥锁,排队来,

    https://github.com/LKaiGuo/KGScriptGenerator 喜欢的给我点个星星啊
    u3d萌新QQ群844087555 欢迎进来灌水=。=

    相关文章

      网友评论

          本文标题:一个简易的心跳包 C# Socket (上)

          本文链接:https://www.haomeiwen.com/subject/kogvyctx.html