TCP之心跳包实现思路

简介: 原文 http://www.cnblogs.com/Leo_wl/p/3334040.html 说起网络应用编程,想到最多的就是聊天类的软件。当然,在这类软件中,一般都会有一个用户掉线检测功能。今天我们就通过使用自定义的HeartBeat方式来检测用户的掉线情况。

原文 http://www.cnblogs.com/Leo_wl/p/3334040.html

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

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

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

源码下载

点击这里下载

作者: Leo_wl
         
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息
目录
相关文章
|
网络协议 网络安全 网络性能优化
TCP/UDP区别&&心跳包机制
UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除非是一些拥塞条件下,如流媒体 TCP:传输控制协议:是面连接的那么运行环境必然要求其可靠性不可丢包,有良好的拥塞控制机制如 http ...
2309 0
|
网络协议 Linux Python
为什么基于TCP的应用需要心跳包(TCP keep-alive原理分析)
TCP keep-alive的三个参数 用man命令,可以查看linux的tcp的参数: man 7 tcp 其中keep-alive相关的参数有三个: tcp_keepalive_intvl (integer; default: 75; since Linux 2.
1203 0
|
网络协议 Linux Windows
TCP连接探测中的Keepalive 和心跳包
采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃、当机、网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回。很多时候,这不是我们需要的。
1399 0
|
网络协议 网络安全 C++
TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制.   2. 导致TCP断连的因素 如果网络正常, socket也通过close操作来进行优雅的关闭, 那么一切完美.
1441 0
|
网络协议 数据库
Delphi2010中DataSnap高级技术(5)—建立稳定服务程序之TCP心跳包的使用
为了能让我们的服务程序更加稳定,有些细节问题必须解决。就如上一讲中提到的客户端拔掉网线,造成服务器上TCP变成死连接,如果死连接数量过多,对服务器能长期稳定运行是一个巨大的威胁。
1032 0
|
5月前
|
机器学习/深度学习 人工智能 网络协议
TCP/IP五层(或四层)模型,IP和TCP到底在哪层?
TCP/IP五层(或四层)模型,IP和TCP到底在哪层?
86 4
|
监控 网络协议 网络架构
IP协议【图解TCP/IP(笔记九)】
IP协议【图解TCP/IP(笔记九)】
115 0
|
域名解析 网络协议
IP协议, TCP协议 和DNS 服务分别是干什么的?
大家好,我是阿萨。昨天讲解了网络四层协议[TCP/IP协议族分为哪4层?]今天我们学习下IP 协议, TCP 协议和DNS 协议分别是干什么的。
280 0
IP协议, TCP协议 和DNS 服务分别是干什么的?
|
网络协议
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。