找回密码
 加入
搜索
查看: 6962|回复: 6

[网络通信] (已解决)“嘭、嘭、嘭”---C/S架构下的心跳机制

  [复制链接]
发表于 2014-5-29 13:46:32 | 显示全部楼层 |阅读模式
本帖最后由 lamant 于 2014-6-3 09:52 编辑

新人发帖,如有违规,请莫禁言封号,谢谢。
本人想使用AU3开发多客户端、一服务端。需要使用到心跳机制,即 在线状态实时更新以及掉线自动重连。
搜索网络发现没有人用AU3写心跳机制。
下面是一篇转帖(原文地址:http://www.cnblogs.com/bluebird2 ... /05/12/2044097.html)。
感谢原作者 永恒的bluebird。
请好人写成AU3的方式,造福大众。

使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连

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

【背景】

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

【思考】

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

【概念】

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

【设计实现】

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

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

  1         private void ThreadConnect()
复制代码
2         {
3             do
4             {
5
6                 if (!_bConnected)
7                 {
8                     _bConnected = _sender.Connect(_ip, _port);
9
10                     if (_bConnected)
11                     {
12
13                         Thread threadSendAndReceivePulseMessage = new Thread(new ThreadStart(ThreadSendAndReceivePulseMessage));
14                         threadSendAndReceivePulseMessage.IsBackground = true;
15                         threadSendAndReceivePulseMessage.Start();
16
17                         Thread threadCheckPulseCount = new Thread(new ThreadStart(ThreadCheckPulseCount));
18                         threadCheckPulseCount.IsBackground = true;
19                         threadCheckPulseCount.Start();
20
21                         _pulseCount = 0;
22
23                         OnConnected(new EventArgs());
24                     }
25
26                 }
27                 Thread.Sleep(_connectInterval);
28
29             }
30             while (_bWorking && _bAutoReconnect);
31         }
复制代码



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



  1         private void ThreadSendAndReceivePulseMessage()
复制代码
2         {
3             while (_bWorking && _bConnected)
4             {
5
6                 string recv =  _sender.Receive(64);
7
8
9                 if (recv == "PULSE")
10                 {
11                     _pulseCount = 0;
12
13                     _sender.Send("ALIVE");
14                 }
15                 else
16                 {
17                     _bConnected = false;
18                     _sender.Close();
19                     
20                 }
21                 Thread.Sleep(10);
22             }
23         }
复制代码



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



  1         private void ThreadCheckPulseCount()
复制代码
2         {
3             while (_bWorking && _bConnected)
4             {
5                 Thread.Sleep(_pulseInterval);
6
7                 _pulseCount++;
8
9                 if (_pulseCount > _maxPulseCount)
10                 {
11                     _bConnected = false;
12                     _sender.Close();
13                 }
14
15                 if (!_bConnected)
16                 {
17                     OnDisconnected(new EventArgs());
18                 }
19             }
20         }
复制代码


在服务端,设计思想类似,需要维护一个“在线列表”,并及时和客户端通信,此处省略代码。
发表于 2014-5-29 15:47:44 | 显示全部楼层
楼主想法很好啊,支持
 楼主| 发表于 2014-5-30 08:22:14 | 显示全部楼层
有人帮忙写写吗?
但凡做客户端、服务端的都可以借鉴呢。
发表于 2014-5-30 08:47:14 | 显示全部楼层
弄个定时执行函数不就好了
定时发数据到服务器
服务器解析 再反馈
如果牵涉到多线程问题无法处理
可以改成另开进程处理
 楼主| 发表于 2014-5-30 13:28:55 | 显示全部楼层
回复 4# my788522

谢谢!
我想在服务端能够看到客户端的状态。最好是不占资源的一种方式。
按您的说法,我也不知道怎么弄啊。
发表于 2014-5-30 21:07:11 | 显示全部楼层
回复 5# lamant


  你自己不都说了吗 "心跳"包
客户端发各种状态到服务器 服务器接收后显示 那不是顺理成章的事情么
论占资源 那是写程序流程的事情
发表于 2015-5-28 14:55:38 | 显示全部楼层
嘭、嘭、嘭
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-18 12:00 , Processed in 0.077653 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表