关于长连接聊天时,出现断电断网情况时,收不到离线消息的问题

chosen1cwp

基于workerman开发了一个客服系统,访客端是用的web+flash,客服使用as3写的,假设客服(a电脑)和访客(b电脑)正在通话,然后我把客服所在a电脑的网络关闭掉,访客(b电脑)那边按理应该收到客服离线的消息才对,但是访客一直都没收到客服离线消息,直到我把客服所在a电脑的网络连接上,此时访客(b电脑)就会收到客服的离线消息。

【 对于实时性要求很高的场景,需要客户端回应心跳,比如服务端给某个客户端发了心跳,如果一段时间(比如10秒)没收到客户端的心跳回复就认为链接断开了,服务端就关闭链接 】这个心跳该如何做呢?

【记得workeman中有那个pingpang的心跳检测?是不是呢?】

10077 3 1
3个回答

walkor

这个和TCP传输层协议的实现有关!

非正常关闭对端可能无法立刻感知或者永远无法感知
a端非正常关闭(断电、把网线等)b端不会立刻感知到的,如果二者直接一直没有通信数据(没有keep_alive或者数据交互),则b端永远检测不到a已经断开,这个是TCP的自身机制。

无法立刻感知或者无法感知的原因
a端非正常关闭,b端如果有向a端发送通讯数据(或者有keep_alive),这时很可能会发送超时,然后TCP层会自己会重试,(重试时机及次数等由系统参数决定),重试多次无果后才会关闭链接(这时服务端才得到链接断开的通知,触发onClose),从a端非正常关闭到判断链接断开如果依赖TCP本身的机制可能要持续至少10分钟才能完成,也就导致b端很久才能感知(如果之间没有通讯则永远无法感知)。

要求实时检测解决方案-应用层心跳
如果对于检测链接是否可用实时性要求很高,需要在应用层面做心跳检测,而不是依赖与TCP本身的机制。例如应用每10秒中发送一个心跳给客户端,客户端收到心跳后立刻返回一个回复,如果服务端心跳发出后一段时间(假如也是10秒)后客户端并没有回应心跳,则判断客户端链接已死,就直接断开链接。

workerman里如何解决
更新下代码 版本2.1.2 或者 版本2.1.3都可以
只更新了 applications/XXX/Bootstrap/Gateway.php 和 conf/conf.d/Gateway.conf 两个文件
http://www.workerman.net/workerman下载

配置 conf/conf.d/Gateway.conf
中设置
ping_interval = X
其中X代表gateway多长时间向客户端发送一次心跳数据,单位为秒

设置向客户端发送的心跳请求数据,用文件保存,这里设置成文件的路径,例如
ping_data = ../applications/Chat/ping.data
其中ping.data文件生成方式参考http://wenda.workerman.net/?/question/34

设置
ping_not_response_limit = N
代表客户端连续N次没有回应心跳数据就断开链接,N可以为1

注意:开启workerman心跳检测后客户端必须回应心跳数据,不然会导致链接断开

这里有一个基于workerman开发的客服系统源码,可以直接用。

  • chosen1cwp 2014-08-29

    群主,如果我的ping.data 里面这样写{"type":"Heartbeat","content":"ping","time":1409310503}/n ,那么我在客户端只要接受到的消息的type=Heartbeat时,就返回一个{json}/n 格式的数据就可以了吗?服务器端不需要接收一下吗 ???还是服务器上已经做过接受处理了?如果接受并处理了是在那里处理的?请教一下

  • walkor 2014-08-30

    服务端要接收,接收到忽略就可以了

chosen1cwp

谢谢 大谢啊 群主好人呢

  • 暂无评论
jorry

注意:心跳格式是

自定义字符串+回车

这个回车就是键盘上的enter换行

否则将无法接收到心跳,另外版本也得注意....

  • 暂无评论
年代过于久远,无法发表回答
🔝