TCP之心跳包实现思路

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

心跳包实现思路

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

代码逻辑

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

#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
View Code

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

 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;
View Code

效果图

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

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

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

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

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

源码下载

点击这里下载

=====================2014年9月24日重构版本=======================

用户实体内部通过维护一个timer计数器,实现心跳检测,心跳超时功能。

点击这里下载新版

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值