TCP之心跳包实现思路

  跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
   在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
   心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
   其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
   在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。

   总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

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

心跳包实现思路

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

代码逻辑

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

  View Code

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

  View Code

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

  View Code

效果图

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

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

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

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

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

//转载自网络:http://www.cnblogs.com/scy251147/p/3333957.html   http://blog.youkuaiyun.com/xuyuefei1988/article/details/8279812
### TCP 长连接心跳结构设计实现 #### 心跳的作用 在网络通信中,保持客户端和服务端之间的长时间稳定连接至关重要。为了防止因网络抖动或其他原因导致的异常断开,在TCP长连接中通常会引入心跳机制来检测链路状态并维持连接活跃。 #### 心跳设计原则 - **轻量级**:心跳数据应尽可能简洁,减少带宽占用。 - **周期性发送**:按照一定的时间间隔定期向对方发送探测消息。 - **超时处理**:设定合理的等待响应时间;如果超过该时限仍未收到回应,则认为连接已失效。 - **安全性考虑**:可以加入身份验证信息确保合法性。 #### 实现方式之一 - MAVLink协议风格的心跳报文构建方法 基于提供的`connection.send2()`函数调用形式[^1],这里给出一种可能的心跳定义: ```cpp struct HeartbeatPacket { uint8_t system_id; // 系统ID uint8_t component_id; // 组件ID uint8_t type; // 设备类型编码 uint8_t autopilot_type; // 自驾仪类型编码 uint16_t mode; // 当前飞行模式位掩码 uint32_t custom_mode; // 用户自定义模式字段 uint8_t system_status; // 系统状态枚举值 void send(int linkId, int64_t timestamp, const char* secretKey){ connection.send2( system_id, component_id, *this, /* 将整个结构体作为heartbeat参数 */ linkId, timestamp, secretKey); } }; ``` 此代码片段展示了如何创建一个类似于MAVLink标准中的心跳,并通过给定接口将其发出。实际应用时可根据具体需求调整各成员变量的意义及其取值范围。 对于Redis集群节点间通讯而言,除了常规的数据交互外同样适用上述思路来进行健康状况监测[^2]。不过需要注意的是,默认情况下这些内部管理流量走的是独立于对外服务之外的一个特殊监听端口(即命令端口号加一万),因此配置防火墙策略时要特别留意这一点以免造成不必要的阻塞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值