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 = ;
}
}
#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之心跳包实现思路的更多相关文章
- Tcp之心跳包
Tcp之心跳包 心跳包 跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着. 事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很 ...
- TCP socket心跳包示例程序
在做游戏开发时,经常需要在应用层实现自己的心跳机制,即定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性. 在TCP socket心跳机制中,心跳包可以由服务器发送给客户端 ...
- Socket之心跳包实现思路
由于最近要做一个客户端,但是要求有一个掉线检测的功能,下面让我们看看使用自定义的HeartBeat方式来检测客户端的连接情况. 心跳包的实现思路: 客户端连接上服务端后,在服务端会维护一个在线客户端列 ...
- 闲说HeartBeat心跳包和TCP协议的KeepAlive机制
很多应用层协议都有HeartBeat机制,通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线,并传输一些可能必要的数据.使用心跳包的典型协议是IM,比如QQ/MSN/飞信等协议. ...
- TCP连接探测中的Keepalive和心跳包
TCP连接探测中的Keepalive和心跳包 tcp keepalive 心跳 保活 Linuxtcp心跳keepalive保活1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 ...
- TCP连接探测中的Keepalive 和心跳包
采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...
- TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...
- tcp/心跳包
1,http://blog.csdn.net/yuzhiyuxia/article/details/7857508 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时 ...
- TCP/UDP区别&&心跳包机制【转】
转自:https://www.jianshu.com/p/6d93a3c21c34 UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除 ...
随机推荐
- 【转】Visual Studio项目相对路径的设置,实用
这篇文章主要写给那些以前没有用过VS的新手,同时也是自己学习经验的积累,高手就不用看了以免浪费您宝贵的时间. 在VS的工程中常常要设置头文件的包含路径,当然你可以使用绝对路径,但是如果你这样设置了你只 ...
- IOS开发关于测试的好的网址资源
1. 高级自动化单元测试,推荐看LeanCloud 工程师的李智维的自动化单元测试的直播录影李智维的演示github 2.iOS开发-单元测试 这只是一篇简单的ios测试介绍 3.iOS单元测试 来自 ...
- js 毫秒 转 时间 日期 yyyy-mm-dd hh-mm-ss
//格式化时间 var format = function(time, format){ var t = new Date(time); var tf = function(i){return (i ...
- XP重装之后蓝屏
最近帮公司的电脑重装XP系统,发现重装之后电脑重启的时候蓝屏 解决方法:开机-->f2-->找到SATA Configration --> 选择ide 重启,就ok了
- System占用端口80
可尝试如下结束System进程: 开始——设置——控制面板——管理工具——服务结束系统服务项:World Wide Web Publishing Service
- Mysql中的存储过程
什么是存储过程 简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法: ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功 ...
- iptables & selinux
iptables -F getenforce setenforce 0 可以临时关闭,但重启之后还是会变成原来的状态. vi /etc/sysconfig/selinux 把里边的一行改为 SELIN ...
- oracle表空间相关
数据库被划分为若干个表空间,每个表空间内保存一组相关的逻辑对象.每个表空间由一个或者多个数据文件组成.oracle中的数据逻辑上存储在表空间里,物理上存储在属于该表空间的数据文件里.表空间是用户和物理 ...
- windows 进程管理器中的内存是什么意思?
*内存 - 工作集:私人工作集中的内存数量与进程正在使用且可以由其他进程共享的内存数量的总和. *内存 - 峰值工作集:进程所使用的工作集内存的最大数量. *内存 - 工作集增量:进程所使用的工作集内 ...
- 限制input输入类型(多种方法实现)
1.只能输入和粘贴汉字 <input onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste= ...