openfire client聊天消息交互和存储离线(在线)消息记录策略

来源:互联网 发布:淘宝根据图片搜索 编辑:程序博客网 时间:2024/06/13 21:04
【0】如何将离线消息存档,且在接收者上线之后,推送消息到接收者
发送方发送消息 -> 检测接收方是否在线 ->-> y -> 发送在线消息 -> 发送成功后,存档到消息记录;-> n -> 修改数据包(XML流) 发送离线消息 ->  存档到消息记录 -> 不断检测某离线消息的接收方是否在线-> y -> 推送离线消息记录(未读)到 刚刚登陆的离线用户;-> n -> 继续检测;

【1】消息交互
1)intro:  以下消息内容
是小生我从 smack client 发送 消息(hello, abcdefg) 和另外一个 client 与 的 消息交互情况; 
2)接收方离线和发送方在线,而后接收方在线的情况
Attention)incoming(true->sender,false->receiver), processed(true->after processed, false->before processed)
step1)发送msg时,接收者离线;(openfire处理前)
<message to="tangtang@lenovo-pc" id="8akb9-36" type="chat" from="pacoson@lenovo-pc/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread></message>org.jivesoftware.openfire.session.LocalClientSession@1960f3cb status: 3 address: pacoson@lenovo-pc/Smack id: 8vqkiso6gv presence: <presence id="8akb9-34" from="pacoson@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = true, processed = false
step2)发送msg时,接收者离线;(openfire处理后)
<message to="tangtang@lenovo-pc" id="8akb9-36" type="chat" from="pacoson@lenovo-pc/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread></message>org.jivesoftware.openfire.session.LocalClientSession@1960f3cb status: 3 address: pacoson@lenovo-pc/Smack id: 8vqkiso6gv presence: <presence id="8akb9-34" from="pacoson@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = true, processed = true
Attention)
A1)以上就是当发送者在线,而接收者离线的openfire消息记录;
A2)以下是 接收者登录后的 openifre 消息记录;

step3)接收者登录在线(openfire处理前)
<message to="tangtang@lenovo-pc" id="8akb9-36" type="chat" from="pacoson@lenovo-pc/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread><delay xmlns="urn:xmpp:delay" from="lenovo-pc" stamp="2016-07-18T00:39:29.759Z"/></message>org.jivesoftware.openfire.session.LocalClientSession@46cc3cbd status: 3 address: tangtang@lenovo-pc/Smack id: 4qrph1nzci presence: <presence id="2h2Pk-7" from="tangtang@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = false, processed = false
step4)接收者登录在线(openfire处理后)
<message to="tangtang@lenovo-pc" id="8akb9-36" type="chat" from="pacoson@lenovo-pc/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread><delay xmlns="urn:xmpp:delay" from="lenovo-pc" stamp="2016-07-18T00:39:29.759Z"/></message>org.jivesoftware.openfire.session.LocalClientSession@46cc3cbd status: 3 address: tangtang@lenovo-pc/Smack id: 4qrph1nzci presence: <presence id="2h2Pk-7" from="tangtang@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = false, processed = true
Conclusion)openfire 对离线消息的处理: 当接收者不在线的时候,openfire 会把 msg 存储到 ofoffline 这个数据库表中;当 接收者登录在线后,openfire 会把该消息push 给 接收者,因而接收者在线后接受 openfire 推送的离线消息 后,会发送 响应消息(参见session 的 from 元素值);之后openfire 会将该消息从 ofoffline 表中清空(即时删除已经发送到用户的离线消息);


3)接收方和发送方都在线的情况
step1)发送方发送消息(处理前)
<message to="tangtang@lenovo-pc" id="8akb9-76" type="chat" from="pacoson@lenovo-pc/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>org.jivesoftware.openfire.session.LocalClientSession@647c5490 status: 3 address: pacoson@lenovo-pc/Smack id: 30glj4xlhu presence: <presence id="8akb9-72" from="pacoson@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = true, processed = false
step2)接收方接收消息(处理前)
<message to="tangtang@lenovo-pc" id="8akb9-76" type="chat" from="pacoson@lenovo-pc/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>org.jivesoftware.openfire.session.LocalClientSession@32e2ab29 status: 3 address: tangtang@lenovo-pc/Smack id: 3t4gvqjm80 presence: <presence id="ZvrMI-7" from="tangtang@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = false, processed = false
step3)接收方接收消息(处理后)
<message to="tangtang@lenovo-pc" id="8akb9-76" type="chat" from="pacoson@lenovo-pc/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>org.jivesoftware.openfire.session.LocalClientSession@32e2ab29 status: 3 address: tangtang@lenovo-pc/Smack id: 3t4gvqjm80 presence: <presence id="ZvrMI-7" from="tangtang@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = false, processed = true
step4)发送方发送消息(处理后)
<message to="tangtang@lenovo-pc" id="8akb9-76" type="chat" from="pacoson@lenovo-pc/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>org.jivesoftware.openfire.session.LocalClientSession@647c5490 status: 3 address: pacoson@lenovo-pc/Smack id: 30glj4xlhu presence: <presence id="8akb9-72" from="pacoson@lenovo-pc/Smack">  <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" node="http://www.igniterealtime.org/projects/smack" ver="os2Kusj3WEOivn5n4iFr/ZEO8ls="/></presence>incoming = true, processed = true

Conclusion) 
C1)我们发现,不管是发送在线消息 还是 离线消息,在openfire 处理前后,都可以对消息进行拦截;
C2)根据以上打印info,我们计划在 incoming = true, processed = true 的case下 存储消息记录;
C3) 如果接收方成功接收消息后(incoming = false, processed = true),我们存储在线消息,有且仅在该case下存储消息到 ofchatlog 数据库表;如果没有接收方的响应信息(incoming 始终等于true,即session.jsi 始终是 发送者,没有接收者,表明接收者离线),openfire会存储离线消息; 当离线的接收者登录后,openfire 推送离线消息给 该接收者(参见“2->step3,step4”的交互消息步骤),我们就在 incoming = false, processed = true的case下 将该消息转储到到 ofchatlog;
C4)一句话说完,我们的ChatLog 插件 涉及的 ofchatlog 数据库表 只存储 在线消息,而离线消息存储在 ofoffline(owned by openfire);所以当接收者离线的时候,离线消息不会存储到 ofchatlog,而是会存储到 ofoffline,离线用户登录后,会将 消息从 ofoffline 转储到 ofchatlog;
<pre name="code" class="java">public class ChatlogPlugin implements PacketInterceptor, Plugin {private static final Logger log = LoggerFactory.getLogger(ChatlogPlugin.class);private static PluginManager pluginManager;private static ChatlogManager logsManager;// Hook for intercpetornprivate InterceptorManager interceptorManager;private PresencePlugin presencePlugin;public ChatlogPlugin() {interceptorManager = InterceptorManager.getInstance();logsManager = ChatlogManager.getInstance();}/** * <b>function:</b> 拦截消息核心方法,Packet就是拦截消息对象 */@Overridepublic void interceptPacket(Packet packet, Session session,boolean incoming, boolean processed) throws PacketRejectedException {Packet copyPacket = packet.createCopy();if (packet instanceof Message) {Message message = (Message) copyPacket;System.out.println(message.toXML());System.out.println(session);System.out.println("incoming = " + incoming + ", processed = " + processed);if (message.getType() == Message.Type.chat) { // 一对一聊天,单人模式if (!incoming && processed) { // 有且仅在该case下,存储在线消息(或转储离线消息->chatlog 数据库表)logsManager.insert(buildChatlog(packet, incoming, session));} else {return ;}
0 0
原创粉丝点击