C#心跳机制服务器

控制台应用项目

Program.cs

internal class Program
{
    static Server server;
    static void Main(string[] args)
    {
        Server server = new Server(IPAddress.Any,3333);
        server.Start();// 除了服务器监听方法,监听客户连接的方法,扫描客户端是否在线的方法
        //如果监听到有客户端连接的时候,打印哪个终端连入到服务器了 使用时间封装
        server.有客户端连入的事件 += 有客户端连入服务器方法;// 绑定事件
        server.客户端断开事件 += f2;
        server.接受到消息的事件 += f3;
        Console.ReadKey();
    }
    // 相当于点击之后的毁掉方法,在客户端连接成功之后调用这个方法
    public static void 有客户端连入服务器方法(object obj)
    {
        TcpClient t1 = obj as TcpClient;
        Console.WriteLine(t1.Client.RemoteEndPoint+"连接到服务器");
    }
    public static void f2(object obj)
    {
        Console.WriteLine(obj.ToString()+"断开连接");
    }
    public static void f3(TcpClient t1, byte[] b1)
    {
        t1.GetStream().Write(b1, 0, b1.Length);
    }
}

Server.cs

internal class Server
{
    TcpListener listen;
    // 1 通过构造函数创建服务器对象
    public Server(IPAddress ip,int port)
    {
        listen = new TcpListener(ip, port);
    }
    // 2 封装开启监听的方法
    public void Start()
    {
        listen.Start(100);// 开启监听
        // 接受客户端的连接
        StartConnect();
        // 扫描心跳方法
        SaoMiao();
    }
    // 3 接受客户端的连接 封装一监听客户端连接的方法
    // 保存所有的客户端字典,键是ip 值是客户端
    Dictionary<string, TcpClient> clientDic = new Dictionary<string, TcpClient>();
    // 字段保存客户端和当前连接服务器时间点
    Dictionary<string, DateTime> heartDic = new Dictionary<string, DateTime>();
    public event Action<TcpClient> 有客户端连入的事件;   
    void StartConnect()
    {
        Task.Run(() =>
        {
            while (true)// 接入多个客户端
            {
                TcpClient client = listen.AcceptTcpClient();
                string ip = client.Client.RemoteEndPoint.ToString();// 获取远程ip
                // 保存当前客户端
                clientDic.Add(ip, client);

                // 记录当前客户端心跳 链接成功的时候记录当前客户端时间点
                heartDic.Add(ip, DateTime.Now);

                // 调用事件函数 触发事件
                有客户端连入的事件?.Invoke(client);

                // 4接受客户端发来的消息
                ReceivMsg(client);
            }
        });
    }
    // 4 接受客户端发来的消息
    // 封装接受的消息
    public event Action<string> 客户端断开事件;// 当客户端断开时候调用
    public event Action<TcpClient, byte[]> 接受到消息的事件;// 接收到消息调用
    void ReceivMsg(TcpClient t1)
    {
        NetworkStream stream = t1.GetStream();
        string ip = t1.Client.RemoteEndPoint.ToString();
        byte[] bs = new byte[1024];
        Task.Run(() =>
        {
            try
            {
                while (true)
                {
                    int count = stream.Read(bs, 0, bs.Length);
                    // 必须判断是否是心跳包 事先约定好
                    if (count == 0)
                    {
                        // 客户端断开
                        throw new Exception("客户端断开连接");

                    }
                    // 如果接收数据长度不为0
                    // 必须判断是否心跳包 事先约定好:如果数据第一位是0的时候,当成普通包
                    // 如果数据第一位是1说明是心跳包
                    switch (bs[0]) // 判断第一位数据是不是0
                    {
                        case 0: // 普通数据 取出来的时候不需要显示第一位标识符
                            // skip 从第一位开始截取
                            // take 到指定位置的元素为止
                            // 第一位0、1代表是否心跳包标识符
                            // 
                            byte[] body = bs.Skip(1).Take(count-1).ToArray();
                            // 要么群发 要么单发
                            接受到消息的事件?.Invoke(t1,body);
                            break;
                        case 1: // 发的是心跳包
                            // 修改是心跳包发的时间点
                            heartDic[ip] = DateTime.Now;
                            break;
                    }
                }
            }
            catch (Exception e)
            {
                // 从字典里把客户端清除掉
                clientDic.Remove(ip);
                // 如果客户端打开了,打印客户
                客户端断开事件?.Invoke(ip);
                //删除心跳记录
                heartDic.Remove(ip);
            }
        });
    }
    // 遍历所有客户端 扫描是否在未超时时间内
    void SaoMiao()
    {
        Task.Run(() =>
        {
            while (true)
            {
                Thread.Sleep(4000);// 线程休眠4s
                DateTime now1 = DateTime.Now;
                foreach (var item in heartDic) // 遍历所以的心跳记录
                {
                    // now1 当前时间点
                    // item.Value 服务器接受客户端发来的心跳包时间
                    if (now1-item.Value>new TimeSpan(0,0,4))
                    {
                        Console.WriteLine(item.Key+"掉线了");
                    }
                    else
                    {
                        Console.WriteLine(item.Key+"在线");
                    }
                }
            }
        });
    }
    // 无参数的构造函数
    public Server()
    {
    }
    // 群发方法
    public void Send()
    {
    }
    // 指定给谁发
    public void send指定()
    {
    }
    //指定给哪些客户端发
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中实现心跳机制可以通过使用定时器来定期发送心跳消息。下面是一个简单的示例: ```csharp using System; using System.Timers; public class Heartbeat { private Timer timer; public Heartbeat() { timer = new Timer(); timer.Interval = 5000; // 设置心跳间隔时间,单位为毫秒 timer.Elapsed += TimerElapsed; } public void Start() { timer.Start(); } public void Stop() { timer.Stop(); } private void TimerElapsed(object sender, ElapsedEventArgs e) { // 发送心跳消息的逻辑 Console.WriteLine("发送心跳消息"); } } public class Program { public static void Main(string[] args) { Heartbeat heartbeat = new Heartbeat(); heartbeat.Start(); // 保持程序运行 Console.WriteLine("按任意键停止心跳"); Console.ReadKey(); heartbeat.Stop(); } } ``` 在上述示例中,我们使用 `System.Timers.Timer` 类来实现定时器功能。在 `Heartbeat` 类的构造函数中,我们设置了定时器的间隔时间为 5000 毫秒(即 5 秒),并订阅了 `Elapsed` 事件。 在 `TimerElapsed` 方法中,你可以实现发送心跳消息的逻辑。可以根据具体需求,使用网络请求、发送消息等方式来实现。 在 `Program` 类的 `Main` 方法中,我们创建了一个 `Heartbeat` 对象,并调用 `Start` 方法来开始心跳。通过按任意键来停止心跳。你可以根据实际需求,在 `Stop` 方法中处理停止心跳的逻辑。 请注意,以上只是一个简单的示例,具体的实现方式可能会因情况而异。你可以根据项目需求进行适当调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值