说起网络应用编程,想到最多的就是聊天类的软件。当然,在这类软件中,一般都会有一个用户掉线检测功能。今天我们就通过使用自定义的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 = ;
}
}
#endregion

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

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

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

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

效果图

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

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

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

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

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

源码下载

点击这里下载

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

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

点击这里下载新版

TCP之心跳包实现思路的更多相关文章

  1. Tcp之心跳包

    Tcp之心跳包 心跳包 跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着. 事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很 ...

  2. TCP socket心跳包示例程序

    在做游戏开发时,经常需要在应用层实现自己的心跳机制,即定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性. 在TCP socket心跳机制中,心跳包可以由服务器发送给客户端 ...

  3. Socket之心跳包实现思路

    由于最近要做一个客户端,但是要求有一个掉线检测的功能,下面让我们看看使用自定义的HeartBeat方式来检测客户端的连接情况. 心跳包的实现思路: 客户端连接上服务端后,在服务端会维护一个在线客户端列 ...

  4. 闲说HeartBeat心跳包和TCP协议的KeepAlive机制

    很多应用层协议都有HeartBeat机制,通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线,并传输一些可能必要的数据.使用心跳包的典型协议是IM,比如QQ/MSN/飞信等协议. ...

  5. TCP连接探测中的Keepalive和心跳包

    TCP连接探测中的Keepalive和心跳包 tcp keepalive 心跳 保活 Linuxtcp心跳keepalive保活1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 ...

  6. TCP连接探测中的Keepalive 和心跳包

    采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...

  7. TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活

    1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...

  8. tcp/心跳包

    1,http://blog.csdn.net/yuzhiyuxia/article/details/7857508 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时 ...

  9. TCP/UDP区别&&心跳包机制【转】

    转自:https://www.jianshu.com/p/6d93a3c21c34 UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除 ...

随机推荐

  1. 明明已经执行Log.i,偏偏打不出日志

    Android内打日志用的当然是Log.i(tag,string),调试时的日志输出可以很快的反映一些问题,方便我们跟进. 但是如果连日志都打不出来了怎么办呢,我今天就遇到了比较坑的问题.项目里别的日 ...

  2. Objective-C Reflection(Objective-C 反射机制)实用随笔笔记(持续更新)

    前言:本篇文章就"Objective-C 反射机制"使用方面进行叙述,不会涉及太多理论论述,因为"Objective-C 反射机制"理论论述在网上搜索一大把,本 ...

  3. Swift字符与字符串

    学习来自<极客学院:Swift中的字符串和集合> 工具:Xcode6.4 直接上基础的示例代码,多敲多体会就会有收获:百看不如一敲,一敲就会 import Foundation /**** ...

  4. JavaScript Patterns 2.9 Coding Conventions

    It’s important to establish and follow coding conventions—they make your code consistent, predictabl ...

  5. Java内存模型的历史变迁

    转自:http://www.csdn.net/article/2015-05-20/2824722-Java 摘要:本文通过介绍Java的新/旧内存模型,来展示Java技术的历史变迁. 本文通过介绍J ...

  6. cocos2d-x之xml文件读取初试

    auto doc=new tinyxml2::XMLDocument(); doc->Parse(FileUtils::getInstance()->getStringFromFile(& ...

  7. centos6.7 安装Docker

      一.查看系统版本 [root@localhost ~]# cat /etc/redhat-release CentOS release 6.7 (Final) 二.安装EPEL 1.进入cento ...

  8. hiveql basic

    set hive.cli.print.current.db=true; set hive.mapred.mode=strict; set hive.mapred.mode=nonstrict; SHO ...

  9. Ajax与用户交互的存储格式JSON

    数据存储是JavaScript的核心功能,这是一个在学习前期的一个容易让人迷惑的问题.它并不是那种像页面滑动.幻灯片展示.淡入淡出等吸引人眼球的特效.适当的存放好数据,就有利于我们组织起结构,又能使应 ...

  10. Half Wavelength Dipole Antenna

    Reference : 1. wikipedia The dipole antenna is the simplest and most widely used class of antenna.It ...