zoukankan      html  css  js  c++  java
  • TCP之心跳包实现思路

    TCP之心跳包实现思路

    说起网络应用编程,想到最多的就是聊天类的软件。当然,在这类软件中,一般都会有一个用户掉线检测功能。今天我们就通过使用自定义的HeartBeat方式来检测用户的掉线情况。

    心跳包实现思路

    我们采用的思路是:客户端连接上服务端以后,服务端维护一个在线用户字典,客户端每隔一段时间,向服务器发送一个心跳包,服务器接收到包以后,字典数据的值都会更新为0;一旦服务端超过规定时间没有接收到客户端发来的包,字典数据将会递增加一,当字典数据的值累计大于等于三,则视为掉线。

    代码逻辑

    客户端每隔一段时间,发送一个心跳包:

     View Code

    #region 心跳Timer计数事件
    private void heartbeatTimer_Tick(object sender, EventArgs e)
    {
    currentCount++;
    if (currentCount == heartbeatCount)
    {
    txtMessage.Append("开始发送心跳包");
    MessageEntity entity = new MessageEntity();
    entity.MessageType = MessagePicks.Heartbeat;
    entity.NickName = loginName;

    WriteToStream(entity);
    currentCount = 0;
    }
    }
    #endregion

    在服务端,会开启一个定时器,定时将userOnLineCounter中的值递增加一。如果此时收到客户端的心跳包,则将userOnLineCounter中的值重置。

     View Code

    private void heartbeatTimer_Tick(object sender, EventArgs e)
    {
    tickCountInStep++;
    if (tickCountInStep == tickCount)
    {
    if (userCollection.Count > 0)
    {
    //计数器自动递增
    expiryCountInStep++;
    foreach (User user in userLists)
    {
    userOnLineCounter[user]++;
    }
    //连续监测三次之后,开始监测集合中的掉线情况
    if (expiryCountInStep == expiryCount)
    {
    //寻找集合中“掉线”的用户
    var disconnectedUsers = userOnLineCounter.Where(p => p.Value >= 3).ToList();
    foreach (var disconnectedUser in disconnectedUsers)
    {
    txtLog.Append("用户" + disconnectedUser.Key.name + "掉线!");

    //删除集合中被视为掉线的用户
    userLists.Remove(disconnectedUser.Key);
    userOnLineCounter.Remove(disconnectedUser.Key);

    //开始广播发送掉线用户
    MessageEntity entity = new MessageEntity();
    entity.MessageType = MessagePicks.OffLine;
    EndPoint curOfflineUserEP = disconnectedUser.Key.client.Client.RemoteEndPoint;
    string userName = disconnectedUser.Key.name;
    entity.MessageContentEx.Add(curOfflineUserEP, userName);

    ObjectInversion inversion = new ObjectInversion();
    byte[] byteArr = inversion.SerializeTo((object)entity);

    try
    {
    foreach (User user in userLists)
    {
    user.writer.Write(byteArr);
    user.writer.Flush();
    }
    }
    catch { }
    }
    expiryCountInStep = 0;
    }
    }
    tickCountInStep = 0;
    }
    }
    }

    收到客户端心跳包,自动重置计数器。

     View Code

    case MessagePicks.Heartbeat:
    txtLog.Append("收到客户端" + entity.NickName + "的心跳回应包.");
    if (userOnLineCounter.ContainsKey(user))
    userOnLineCounter[user] = 0;
    else
    userOnLineCounter.Add(user, 0);
    break;

    效果图

    (图1:三个客户端连接一个服务器)

    (图2:用户“上善若水”掉线)

    (图3:用户“古道热肠”掉线)

     程序暂时还未完全完成,有需要的可以参考下。当然也期待大家的各种思路。

    代码很丑,期望大家指点下重构的方法。

    源码下载

    点击这里下载

  • 相关阅读:
    ASP.NET Core路由中间件[4]: EndpointRoutingMiddleware和EndpointMiddleware
    ASP.NET Core路由中间件[3]: 终结点(Endpoint)
    ASP.NET Core路由中间件[2]: 路由模式
    ASP.NET Core路由中间件[1]: 终结点与URL的映射
    [LeetCode] 994. Rotting Oranges 腐烂的橘子
    [LeetCode] 993. Cousins in Binary Tree 二叉树的表兄弟节点
    [LeetCode] 992. Subarrays with K Different Integers 有K个不同整数的子数组
    [LeetCode] 991. Broken Calculator 损坏的计算器
    [LeetCode] 1143. Longest Common Subsequence 最长公共子序列
    [LeetCode] 990. Satisfiability of Equality Equations 等式方程的可满足性
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3334040.html
Copyright © 2011-2022 走看看