博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[心跳] 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连...
阅读量:5922 次
发布时间:2019-06-19

本文共 2842 字,大约阅读时间需要 9 分钟。

此文讲述的内容是一个实际项目开发中的一部分内容,笔者将亲身经历写成文章。

【背景】

现 需要实现这样的功能:有多个客户端连着同一个服务器。服务器和客户端之间需要“互相”知道彼此的连接状态。比如在某一时刻,服务器需要知道当前有多少个客 户端正在和其通信;某一个时刻,某个客户端需要知道自己是否和服务器保持连接。如果在某一时刻,一个客户端关闭了,服务端应能及时感觉到;同样,如果服务 端被关闭,所有的客户端应能及时感觉到,并作出一些反应。

【思考】

看 到这个需求,直观上的反应就是在服务端维护一个在线列表。当服务端的监听器监听到一个连接,就把该连接对应的客户端信息加入这个在线列表。这样就完成了对 上线状况的记录。但下一个问题是如何让服务器知道客户端的离线状况呢?我们可能会想到,让客户端在关闭前发送一个消息到服务端,服务端收到消息后就把客户 端置为离线状态。但是,在更多情况下,客户端并不是这么“友好”地关闭的。应用程序崩溃、网络连接被重置、机器死机等情况下,客户端来不及发送“离线通 知”给服务端就挂掉了。这时,需要有一套机制,能让服务端和客户端彼此对对方的在线状态保持清醒。

【概念】

何谓“心跳”? 心跳就是指“活着”的客户端或服务端每隔一定的时间就互相发送接收一个消息,告诉对方自己“活着”。当客户端或服务端超过一定的时间间隔尚未收到对方的“心跳”消息,就认为对方“死了”。这就是“心跳机制”的核心思想。

【设计实现】

在客户端,除了 UI 外,需要三个线程在后台工作。

1,自动连接的线程。该线程可以实现每隔指定时间就检查一次连接状态,如果发现当前是“离线”状态,就自动发起向服务端的一次连接。

 

private void ThreadConnect() {            do            {                if (!_bConnected)                {                    _bConnected = _sender.Connect(_ip, _port);                    if (_bConnected)                    {                        Thread threadSendAndReceivePulseMessage = new Thread(new ThreadStart(ThreadSendAndReceivePulseMessage));                        threadSendAndReceivePulseMessage.IsBackground = true;                        threadSendAndReceivePulseMessage.Start();                        Thread threadCheckPulseCount = new Thread(new ThreadStart(ThreadCheckPulseCount));                        threadCheckPulseCount.IsBackground = true;                        threadCheckPulseCount.Start();                        _pulseCount = 0;                        OnConnected(new EventArgs());                    }                }                Thread.Sleep(_connectInterval);            }            while (_bWorking && _bAutoReconnect);}

 

 

 

2,收发“心跳”消息的线程。该线程和服务端进行收发心跳消息。注意每收到服务器发来的消息,应将心跳计数器置零。心跳计数器的含义是已经隔了多少个心跳周期没收到心跳消息了。

 

private void ThreadSendAndReceivePulseMessage(){            while (_bWorking && _bConnected)            {                string recv =  _sender.Receive(64);                if (recv == "PULSE")                {                    _pulseCount = 0;                    _sender.Send("ALIVE");                }                else                {                     _bConnected = false;                    _sender.Close();                                    }                Thread.Sleep(10);            }}

 

3,检查心跳计数器的值的线程。该线程每隔指定的时间间隔就检查一次心跳计数器,当发现已经超过指定心跳周期(比如3次)未接收到心跳消息,就认为是离线了,则进行相应的处理。

private void ThreadCheckPulseCount(){            while (_bWorking && _bConnected)            {                Thread.Sleep(_pulseInterval);                _pulseCount++;                if (_pulseCount > _maxPulseCount)                {                    _bConnected = false;                    _sender.Close();                }                if (!_bConnected)                {                    OnDisconnected(new EventArgs());                }            }}

在服务端,设计思想类似,需要维护一个“在线列表”,并及时和客户端通信,此处省略代码。

 

 

转载地址:http://epivx.baihongyu.com/

你可能感兴趣的文章
大叔也说Xamarin~Android篇~Activity之间传递数组
查看>>
Hibernate关联关系映射之一对一(主键关联)
查看>>
iOS开发-使用Storyboard进行界面跳转及传值
查看>>
iOS开发-装饰模式
查看>>
第七章 常用Java集合类总结
查看>>
python数字图像处理(2):图像的读取、显示与保存
查看>>
SQL Server代理(3/12):代理警报和操作员
查看>>
jsp截取字符串
查看>>
javascript 高级选择器:querySelector 和 querySelectorAll
查看>>
memcached +mysql+php 例子
查看>>
广东程序员在加利福尼亚
查看>>
outline属性
查看>>
Java Swing界面编程(27)---JRadioButton事件处理
查看>>
iOS 加密的3种方法
查看>>
Hbase分布式安装部署过程
查看>>
Change Fragment layout on orientation change
查看>>
C++中public、protected及private使用方法
查看>>
Android复习笔记--Activity
查看>>
C++ Dll 编写入门
查看>>
[CareerCup] 18.10 Word Transform 单词转换
查看>>