使用C# SocketTCP开发网络游戏ForestWars(四) 实现心跳检测

版权声明:未经同意,请勿转载 https://blog.csdn.net/qq_25542475/article/details/86839220
本章主要讲述如何实现心跳检测。

一 为什么要进行心跳检测

正常情况下,断开TCP连接会经历四次挥手。然而如果客户端电脑死机或者网络断开,便无法实现四次挥手。服务器能够同时连接的客户端数量有限,如果出现太多这样的情况,新连接便无法连入。为了处理这种情况,引入了心跳机制。心跳机制就是规定客户端每隔一段时间要给服务端发送一个特定信号,服务器会记录客户端最后一次发送心跳信号的时间,如果最后发送的心跳时间与现在时间相隔太久,便认为客户端已经断开,于是主动断开连接。

二 业务逻辑的实现

HeartbeatTime.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TCP_Sever.Conns;

namespace TCP_Sever.Timer
{
    class HeartbeatTime
    {
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return (long)ts.TotalSeconds;
        }
        /// <summary>
        /// 心跳时间
        /// </summary>
        public static long heartbeattimer = 180;
        /// <summary>
        /// 主定时器
        /// </summary>
        private static System.Timers.Timer timer = new System.Timers.Timer(1000);
        /// <summary>
        /// 开始心跳检测
        /// </summary>
        public static void Start()
        {
            //定时器
            timer.Elapsed += new System.Timers.ElapsedEventHandler(HandleMainTimer);
            timer.AutoReset = false;
            timer.Enabled = true;
        }
        /// <summary>
        /// 定时事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void HandleMainTimer(object sender, System.Timers.ElapsedEventArgs e)
        {
            Console.WriteLine("[心跳检测中......]");
            long Now_Timer = GetTimeStamp();
            for (int i = 0; i < Conn_Helper.Conns.Length; i++)
            {
                if (Conn_Helper.Conns[i] == null) continue;
                if (!Conn_Helper.Conns[i].isUse) continue;
                if (Conn_Helper.Conns[i].last_HeartTime < Now_Timer - heartbeattimer)
                {
                    lock (Conn_Helper.Conns[i])
                        Conn_Helper.Conns[i].Client_Close();
                }
            }
            //循环检测
            timer.Start();
        }
        /// <summary>
        /// 更新心跳时间
        /// </summary>
        /// <param name="conn"></param>
        public static void Update_last_HeatTime(Conn conn)
        {
            lock (conn)
                conn.last_HeartTime = GetTimeStamp();
            Console.WriteLine("更新时间" + conn.Get_ClientAddress());
        }
    }
}

在Conn类中添加字段

  /// <summary>
        /// 心跳时间
        /// </summary>
        public long last_HeartTime = 0;

Conn类初始化函数添加

 //初始化心跳时间
            last_HeartTime = HeartbeatTime.GetTimeStamp();

Sever类的开启服务器函数中添加

 //开启心跳检测
            HeartbeatTime.Start();

三 调试

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_25542475/article/details/86839220
今日推荐