public class QoS4SendDaemon
extends java.lang.Object
当前MobileIMSDK的QoS机制支持全部的C2C、C2S、S2C共3种消息交互场景下的 消息送达质量保证.
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
FIXME: 按照目前MobileIMSDK通信机制的设计原理,有1种非常极端的情况目前的QoS 重传绝对不会成功,那就是当对方非正常退出,而本地并未及时(在服务会话超时时间内)收到 他下线通知,此时间间隔内发的消息,本地将尝试重传。但对方在重传重试期限内正常登陆也将 绝不会收到,为什么呢?因为对方再次登陆时user_id已经更新成新的了,之前的包记录的发送 目的地还是老user_id。这种情况可以改善,那就是这样的包里还记录它的登陆名,服务端将据 user_id尝试给目标发消息,但user_id不存在的情况下(即刚才这种情况)可以用登陆名尝试 找到它的新user_id,从而向新user_id发消息就可以让对方收到了。目前为了最大程度保证算 法的合理性和简洁性暂不实现这个了,好在客户端业务层可无条件判定并提示该消息没有成功发 送,那此种情况在应用层的体验上也是可接受的!
限定符和类型 | 字段和说明 |
---|---|
static int |
CHECH_INTERVAL
QoS质量保证线程心跳间隔(单位:毫秒),默认5000ms.
|
static int |
MESSAGES_JUST$NOW_TIME
“刚刚”发出的消息阀值定义(单位:毫秒),默认3000毫秒。
|
static int |
QOS_TRY_COUNT
一个包允许的最大重发次数,默认2次。
|
限定符和类型 | 方法和说明 |
---|---|
void |
clear()
清空缓存队列。
|
static QoS4SendDaemon |
getInstance() |
boolean |
isRunning()
线程是否正在运行中。
|
protected void |
notifyMessageLost(java.util.ArrayList<net.openmob.mobileimsdk.server.protocal.Protocal> lostMessages)
将未送达信息反馈给消息监听者。
|
void |
put(net.openmob.mobileimsdk.server.protocal.Protocal p)
推入一个消息包的指纹特征码.
|
void |
remove(java.lang.String fingerPrint)
移除一个消息包.
|
void |
run() |
int |
size()
队列大小.
|
void |
startup(boolean immediately)
启动线程。
|
void |
stop()
无条件中断本线程的运行。
|
public static final int CHECH_INTERVAL
间隔越短则为用户重发越即时,但将使得重复发送的可能性增大(因为可能在应答 包尚在途中时就判定丢包了的错误情况),当然,即使真存在重复发送的可能也是无害的 ,因为MobileIMSDK的QoS机制本身就有防重能力。请根据您的应用所处的网络延迟情况进行 权衡,本参数为非关键参数,如无特殊情况则建议无需调整本参数。
public static final int MESSAGES_JUST$NOW_TIME
此阀值的作用在于:在QoS=true的情况下,一条刚刚发出的消息会同时保存到本类中的QoS保证队列, 在接收方的应答包还未被发出方收到时(已经发出但因为存在数十毫秒的网络延迟,应答包正在路上) ,恰好遇到本次QoS质量保证心跳间隔的到来,因为之前的QoS队列罗辑是只要存在本队列中还未被去掉 的包,就意味着是要重传的——那么此逻辑在我们本次讨论的情况下就存在漏洞而导致没有必要的重传了。 如果有本阀值存在,则即使刚刚发出的消息刚放到QoS队列就遇到QoS心跳到来,则只要当前放入队列的时间 小于或等于本值,就可以被认为是刚刚放入,那么也就避免被误重传了。
基于以上考虑,本值的定义,只要设定为大于一条消息的发出起到收到它应答包为止这样一个时间间隔即可 (其实就相于一个客户端到服务端的网络延迟时间4倍多一点点即可)。 此处定为3秒其实是为了保守起见哦。
本参数将决定真正因为UDP丢包而重传的即时性问题,即当MobileIMSDK的UDP丢包时,QoS首次重传的
响应时间为> MESSAGES_JUST$NOW_TIME
(即3000毫秒) 而 <= CHECH_INTERVAL
(即5000毫秒)。
public static final int QOS_TRY_COUNT
次数越多,则整个UDP的可靠性越好,但在网络确实很烂的情况下可能会导致重传的泛滥而失去 “即时”的意义。请根据网络状况和应用体验来权衡设定,本参数为0表示不重传,建议使用1到5 之间的数字。
public static QoS4SendDaemon getInstance()
public void run()
protected void notifyMessageLost(java.util.ArrayList<net.openmob.mobileimsdk.server.protocal.Protocal> lostMessages)
lostMessages
- 已被判定为“消息未送达”的消息列表ClientCoreSDK.getInstance().getMessageQoSEvent()}
public void startup(boolean immediately)
无论本方法调用前线程是否已经在运行中,都会尝试首先调用 stop()
方法,
以便确保线程被启动前是真正处于停止状态,这也意味着可无害调用本方法。
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
immediately
- true表示立即执行线程作业,否则直到 CHECH_INTERVAL
执行间隔的到来才进行首次作业的执行public void stop()
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
public boolean isRunning()
public void put(net.openmob.mobileimsdk.server.protocal.Protocal p)
p
- public void remove(java.lang.String fingerPrint)
此操作是在步异线程中完成,目的是尽一切可能避免可能存在的阻塞本类中的守望护线程.
fingerPrint
- 消息包的特纹特征码(理论上是唯一的)public void clear()
调用此方法可以防止在APP不退出的情况下退出登陆MobileIMSDK时没有清除队列缓存, 导致此时换用另一账号时发生数据交叉。
public int size()
HashMap.size()