吵吵   2015-04-09  阅读:1,227

还记得你刚接触Sokcet编程的时候,思考,腾讯QQ是怎么保持在线的么?

程序员!你的第一个聊天室程序有没有实现过这个问题啊?

吵吵当初无意错过,但是,当我折腾危急值报告系统的时候,我发现又碰上了这个问题!

废话不讲,看看解决思路吧:

1、通过Try Catch(exception)来识别这个sokcet已经断开。

这个似乎是不用动脑子的办法,当一个Socket已经断开的时候,你尝试写入或者读取数据的话,就会产生一个错误,那么通过在异常处理中丢弃这个socket来实现掉线。

尤其值得一说的C#中的socket有一个属性叫做Isconneted,这个属性为true时,并不代表这个socket是连接了的,你必须要读取或者写入sokcet,才能扑捉到异常。

这是微软的bug啊,赤裸裸的bug。脑子进水了!

那么服务端怎么判断它掉线呢,一段时间去尝试读取、或者写入sokcet,通过捕捉异常就可以判断是否掉线了。

2、你以为如上所说的方法是完美了么?非也!不信,你拔掉网线试试。

你会发现读写sokcet正常,但是服务端和客户端的写入都无法被接收到!

这是windows上的实验,不知道linux上是否如此,如有发现,烦请告知。

3、中级杀手锏,心跳机制:

A、客户端每5秒发送一个心跳包,服务端收到心跳包后,将对应sokcet的一个计数值AliveNum清理为0,并发送一个心跳返回包。

B、服务端每5秒查询一次sokcet连接列表,将AliveNum+=1,发现有AliveNum>3的sokcet,则视为断线,并从sokcet列表中移除该sokcet。

C、一般到上面就结束了,但是别忘了,客户端也是需要一个AliveNum来判断是否断线了的,客户端每5秒发送心跳包的时候,就把AlvieNum加1,收到心跳返回包,则将AlvieNum清零。当AliveNum>3的时候,抛弃现有的sokcet,重新去连接服务端。

上面的逻辑完美了没有?没有,如果你仔细思考的话,会发现依旧还有一个问题,当我删除sokcet和增加sokcet同时进行的时候呢,维护sokcet列表就需要考虑一个线程同步的问题,线程同步怎么搞?

自己百度吧。

吵吵微信朋友圈,请付款实名加入:

吵吵 吵吵

一条回应:“危急值报告系统之心跳包的设计”

  1. 小乐丫网说道:

    很是不错的博客

发表评论

电子邮件地址不会被公开。 必填项已用*标注