您的位置:首页 > 理论基础 > 计算机网络

openfire因为网络不稳定而造成消息丢失的解决方案

2015-10-27 18:38 375 查看
1 2

C1 ------- S ------- C2

消息丢失

状态:C1在线,但C2因为网络问题,或是进程被杀死,并且此时服务器还没及时发送ping 进行判断C2是否在线。

第一种情况:

此时,当C1向C2发送消息时,步骤1可以顺利完成,而由于此时S并不知道C2已离线,会和正常情况一样发送消息至C2,但是S不会收到来自步骤2产生的任何错误与提示,S则发送消息后结束整个消息处理,等到C2恢复正常后则会丢失来自C1的消息

第二种情况:

该情况为第一种情况的逆向。当C2向C1发送消息时,步骤2不会完成,因为C2根本没有连接到S,但是C2却没有任何来自步骤2的错误提示,导致C2认为消息已发出,待C2恢复正常后C2断线时的消息全部丢失

初步解决方案(待验证):

第一种情况:

扩展S离线消息处理机制,不光在客户端正常离线时保存客户端收到的消息,非正常离线也会保存,所以在S发送消息至C2置前或置后进行处理,置前是先判断C2是否真正在线,实现方式可以采用发送ping,如果有ping的回应侧发送消息,否则保存离线消息;置后则是先发消息,发送后等待终端的消息回执(XEP-0184)。

第二种情况:

增加客户端消息回执功能(XEP-0184),发送方发送消息时注明需要接收方成功收到消息后进行规定格式的消息回执,以确保消息的正常送达

添加消息回执的消息发送过程



以下节点在服务器端截取

<!--1、C1(用户63)发送消息至C2(用户1580),并且注明需要消息回执-->
<message to="1580@xyb.com"id="Fdb6V-15">
<body>消息内容</body>
<requestxmlns="urn:xmpp:receipts"></request><!--需要消息回执-->
</message>

<!--2、S(服务器)把接收到的消息进行处理(增加from属性)后,发送至C2(用户1580)-->
<message to="1580@xyb.com"id="Fdb6V-15" from="63@xyb.com/Smack">
<body>消息内容</body>
<requestxmlns="urn:xmpp:receipts"></request>
</message>

<!--3、C2(用户1580)接收到来自C1(用户63)的消息后,发送消息回执,message节点的type属性为normal-->
<message to="63@xyb.com/Smack"id="1guiN-36" type="normal">
<receivedxmlns="urn:xmpp:receipts"id="Fdb6V-15"></received><!--received节点下的id的值为已接收到消息的id值(重要)-->
</message>

<!--4、S(服务器)把接收到的消息进行处理(增加from属性)后,发送至C2(用户1580)-->
<message to="63@xyb.com/Smack"id="1guiN-36" type="normal" from="1580@xyb.com/Smack">
<receivedxmlns="urn:xmpp:receipts"id="Fdb6V-15"></received>
</message>


下图上方为客户端C1发出的节点,下方为C2接收到的节点



下图下方为C2接收到信息后发出的消息回执,上方为C1所收到的消息回执



到此为止,上面的测试与产生的数据都是建立在正常的情况之下,也就是C1与C2都是在线的,都是可以收的到消息的,下面进行非正常情况下的测试。

一、 收消息方离线

二、 收消息方非正常在线(不能收到消息,但是服务器认为它可以收到消息)

测试一:

第一步:

我们先关闭一个用户,使其下线,之后再用另一个用户进行发送消息,测试如下:



测试中发送了八条消息,但是收到的消息却是空白的



此时已说明对方未接收到消息。

第二步:

我们让离线的用户重新上线,观察其状态。



接收方接收来自服务器的离线消息后,发送了相应的消息回执到消息发送方,下图为消息发送方接收到的消息回执:



其实上面的测试结果是没有什么争议的,按照openfire的离线消息处理也应该能猜到,但是下面的另一种测试就有点出乎意料了。

第一步:发消息方在线,收消息方离线,发消息方发消息后,就离线

第二步:收消息方上线,可以收到消息,并发送消息回执,

第三步:发消息方上线,可是它却没有收到任何消息回执。

不论这种情况是否正确,或是它产生的原因,先放置在这,最后再总结。

测试二:

第一步:我们先让接收方登录,之后查看openfire的用户列表,确认其真正在线,之后,拔掉接收方的网线,模拟网络变差的情况,之后查看openfire用户列表,发现接收方依旧在线。

第二步,登录消息发送方,之后发送若干条消息,发现并没有消息回执,说明对方未收到消息

第三部:重新使接收方真正上线,发现没有任何离线消息,同样,也没有消息回执。

总结:

不论XEP-0184最重要的目的是什么,此时的表现,它不能完全解决我们的问题,因为它太依赖消息的接收者,并且似乎主要是终端受影响,服务器不需要做什么,所以根据我们的需求整理一下解决方案,时序图如下:



第一部分:消息从发送方到服务器,这里增加消息回执(XEP-0184),可以确保消息真正发送至服务器,并且在等待消息回执时可以增加界面的进度图标显示,或是在消息回执超时后进行标记显示(下图为QQ截图)



第二部分:此时服务器以接收到消息,准备发送至消息接收方。此时,服务器需要发送ping(XEP-0199)实时验证终端是否真正在线(可能离线或是非正常离线),是否可以接受消息,当条件不允许时,服务器会保存离线消息,否则,发送消息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: