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

【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="[email protected]" id="8akb9-36" type="chat" from="[email protected]/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 8vqkiso6gv presence:
<presence id="8akb9-34" from="[email protected]/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="[email protected]" id="8akb9-36" type="chat" from="[email protected]/Smack"><body>hello, abcdefg</body><thread>1d5f0c93-4eb6-4461-a09a-0da6fc9d3ac6</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 8vqkiso6gv presence:
<presence id="8akb9-34" from="[email protected]/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="[email protected]" id="8akb9-36" type="chat" from="[email protected]/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>
[email protected] status: 3 address: [email protected]/Smack id: 4qrph1nzci presence:
<presence id="2h2Pk-7" from="[email protected]/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="[email protected]" id="8akb9-36" type="chat" from="[email protected]/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>
[email protected] status: 3 address: [email protected]/Smack id: 4qrph1nzci presence:
<presence id="2h2Pk-7" from="[email protected]/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="[email protected]" id="8akb9-76" type="chat" from="[email protected]/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 30glj4xlhu presence:
<presence id="8akb9-72" from="[email protected]/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="[email protected]" id="8akb9-76" type="chat" from="[email protected]/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 3t4gvqjm80 presence:
<presence id="ZvrMI-7" from="[email protected]/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="[email protected]" id="8akb9-76" type="chat" from="[email protected]/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 3t4gvqjm80 presence:
<presence id="ZvrMI-7" from="[email protected]/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="[email protected]" id="8akb9-76" type="chat" from="[email protected]/Smack"><body>i am a student.</body><thread>20b6bc6b-64b8-4cc8-a58c-c416090ae1bc</thread></message>
[email protected] status: 3 address: [email protected]/Smack id: 30glj4xlhu presence:
<presence id="8akb9-72" from="[email protected]/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 intercpetorn
	private InterceptorManager interceptorManager;
	private PresencePlugin presencePlugin;

	public ChatlogPlugin() {
		interceptorManager = InterceptorManager.getInstance();
		logsManager = ChatlogManager.getInstance();
	}

	/**
	 * <b>function:</b> 拦截消息核心方法,Packet就是拦截消息对象
	 */
	@Override
	public 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 ;
				}

时间: 2024-11-05 15:37:56

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

OpenFire源码学习之二十五:消息回执与离线消息(下)

这一篇紧接着上面继续了. 方案二 基于redis的消息回执.主要流程分为下面几个步骤: 1)将消息暂存储与redis中,设置好消息的过期时间 2)客户端回执消息id来消灭暂存的消息 3)开通单独线程论坛在第1)步中的消息.根据消息的时间重新发送消息.如果消息第一次存放的时间大雨有效期(自定义10秒),解析消息中的to查找用户是否还在线.如果在则T掉(因为它长时间不理会服务的重要命令),如果不在线则将消息放置离线表. OK,先来看看消息的存储格式吧. 1.MESSAGE消息 用户集合 SADD 

如何设计一套通用消息交互系统

1.如何设计一套通用消息交互系统?(基于小程序与企业微信用户之间)  (1)在线聊天系统是否设计通用? 在线聊天系统,终端隔离,即发送端接受端使用唯一id,用于标识两个人员之间的独立,交互直接根据id直接进行交互,即可以根据令牌进行交互.消息系统并不关心终端用户是什么人,只关注两人之间的聊天. 用意: 聊天系统,不仅可以使用于一个xxxx场景,并且可以用于其他场景,利于电商版本当中商家与用户直接的聊天,等等. (2)消息扩展? 消息平台支持消息扩展,即通过第三方工具来建立未读消息提醒功能,目前系

JMS学习(七)-ActiveMQ消息的持久存储方式之KahaDB存储

一,介绍 自ActiveMQ5.4以来,KahaDB成为了ActiveMQ默认的持久化存储方式.相比于原来的AMQ存储方式,官方宣称KahaDB使用了更少的文件描述符,并且提供了更快的存储恢复机制. 二,KahaDB存储配置 在 conf/activemq.xml 中配置如下: <broker brokerName="broker" ... > <persistenceAdapter> <kahaDB directory="activemq-da

微信开发之消息的接收与相应--消息交互基础(四)

一.消息交互流程 1.用户通过微信客户端向公众号发送消息,消息首先会被微信服务器接收到 2.微信服务器接收到消息后,会根据开发者在接口配置信息中填写的URL,将消息通过HTTP POST发送到公众号服务器 3.公众号服务器接收到消息后,会根据相应的逻辑进行处理 4.处理完成后,公众号服务器会将处理结果发送到微信服务器, 5.微信服务器将公众号服务器返回的消息通过公众账号发送给用户 二.消息的分类 1.请求消息  请求消息是指用户发送给公众号的消息,包括文本消息,图片消息,语音消息,视频消息,地理

转:简单的RTSP消息交互过程

简单的RTSP消息交互过程 C表示RTSP客户端,S表示RTSP服务端 1.   第一步:查询服务器端可用方法 1.C->S:OPTION request       //询问S有哪些方法可用 1.S->C:OPTION response    //S回应信息的public头字段中包括提供的所有可用方法 2.   第二步:得到媒体描述信息 2.C->S:DESCRIBE request      //要求得到S提供的媒体描述信息 2.S->C:DESCRIBE response  

kafka生产、存储、消费消息

Kafka架构组成:由producer(消息生产者).consumer(消息消费者).borker(kafka集群的server,负责处理消息读.写请求,存储消息,在kafka cluster这一层这里,其实里面是有很多个broker).topic(消息队列/分类相当于队列,里面有生产者和消费者模型).zookeeper(元数据信息存在zookeeper中,包括:存储消费偏移量,topic话题信息,partition信息) 这些部分组成. kafka里面的消息是有topic来组织的,简单的我们可

消息队列一:为什么需要消息队列(MQ)?

为什么会需要消息队列(MQ)? ########################################################################################## 主要原因是由于在高并发环境下,由于来不及同步处理,请求往往会发生堵塞,比如说,大量的insert,update之类的请求同时到达MySQL,直接导致无数的行锁表锁,甚至最后请求会堆积过多,从而触发too many connections错误.通过使用消息队列,我们可以异步处理请求,从而

阿里云消息队列Kafka商业化:支持消息无缝迁移到云上

列Kafka彻底解决了开源产品稳定性不足的痛点,可用性达99.9%,数据可靠性99.999999%,并且支持消息无缝迁移到云上. 7月25日,阿里云宣布正式推出消息队列Kafka,全面融合开源生态.在兼容Apache生态的基础上,阿里云消息队列Kafka彻底解决了开源产品稳定性不足的痛点,可用性达99.9%,数据可靠性99.999999%,并且支持消息无缝迁移到云上. Kafka是一个分布式.高吞吐量.高可扩展性的消息队列服务,广泛用于日志收集.监控数据聚合.流式数据处理.在线和离线分析等大数据

MQ消息队列(2)—— Java消息服务接口(JMS)

一.理解JMS   1.什么是JMS?         JMS即Java消息服务(Java Message Service)应用程序接口,API是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建.发送.接收和读取消息.它使分布式通信耦合度更低,消息服务更加可靠以及异步性. 我们可以简单的理解:两个应用程序之间需要进行通信,我们使用一个JMS服务,进行中间的转发,通过JMS 的使用,我们可以解除两个程序之间的耦合. JMS不是消息队列,更不是某种消息队列协议.JMS是Jav